wormchain - contract deploy + test
This commit is contained in:
parent
1f939ea2dd
commit
220a869b7b
|
@ -253,7 +253,7 @@ jobs:
|
||||||
node-version: "16"
|
node-version: "16"
|
||||||
- run: cd clients/js && make test
|
- run: cd clients/js && make test
|
||||||
|
|
||||||
# Verify wormhole chain unit tests
|
# Verify wormchain tests
|
||||||
wormchain:
|
wormchain:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
|
@ -261,11 +261,14 @@ jobs:
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: "1.19.3"
|
go-version: "1.19.3"
|
||||||
- run: |
|
- name: make proto -B && make test
|
||||||
|
run: |
|
||||||
cd wormchain
|
cd wormchain
|
||||||
make proto -B
|
make proto -B
|
||||||
git diff --name-only --exit-code && echo "✅ Generated proto matches committed proto" || (echo "❌ Generated proto differs from committed proto, run \`make proto -B\` and commit the result" >&2 && exit 1)
|
git diff --name-only --exit-code && echo "✅ Generated proto matches committed proto" || (echo "❌ Generated proto differs from committed proto, run \`make proto -B\` and commit the result" >&2 && exit 1)
|
||||||
make test
|
make test
|
||||||
|
- name: deploy-test
|
||||||
|
run: cd wormchain && make contracts-deploy-test
|
||||||
|
|
||||||
# Verify go sdk unit tests
|
# Verify go sdk unit tests
|
||||||
sdk_vaa:
|
sdk_vaa:
|
||||||
|
|
|
@ -13,6 +13,8 @@ venv
|
||||||
.env
|
.env
|
||||||
.env.hex
|
.env.hex
|
||||||
.env.0x
|
.env.0x
|
||||||
|
devnet-consts.json
|
||||||
|
!/scripts/devnet-consts.json
|
||||||
bigtable-admin.json
|
bigtable-admin.json
|
||||||
bigtable-writer.json
|
bigtable-writer.json
|
||||||
**/cert.pem
|
**/cert.pem
|
||||||
|
|
|
@ -37,6 +37,9 @@ ENV NUM_GUARDIANS=$num_guardians
|
||||||
# run guardian-set-init.sh to create env files with the init state for NUM_GUARDIANS
|
# run guardian-set-init.sh to create env files with the init state for NUM_GUARDIANS
|
||||||
RUN ./scripts/guardian-set-init.sh $NUM_GUARDIANS
|
RUN ./scripts/guardian-set-init.sh $NUM_GUARDIANS
|
||||||
|
|
||||||
|
# run distribute-devnet-consts.sh to copy devnet-consts.json to chain dirs for use
|
||||||
|
RUN ./scripts/distribute-devnet-consts.sh
|
||||||
|
|
||||||
FROM scratch AS const-export
|
FROM scratch AS const-export
|
||||||
COPY --from=const-build /scripts/.env.0x ethereum/.env
|
COPY --from=const-build /scripts/.env.0x ethereum/.env
|
||||||
COPY --from=const-build /scripts/.env.hex solana/.env
|
COPY --from=const-build /scripts/.env.hex solana/.env
|
||||||
|
@ -45,3 +48,6 @@ COPY --from=const-build /scripts/.env.hex cosmwasm/deployment/terra2/tools/.env
|
||||||
COPY --from=const-build /scripts/.env.hex algorand/.env
|
COPY --from=const-build /scripts/.env.hex algorand/.env
|
||||||
COPY --from=const-build /scripts/.env.hex near/.env
|
COPY --from=const-build /scripts/.env.hex near/.env
|
||||||
COPY --from=const-build /scripts/.env.hex aptos/.env
|
COPY --from=const-build /scripts/.env.hex aptos/.env
|
||||||
|
COPY --from=const-build /scripts/.env.hex wormchain/contracts/tools/.env
|
||||||
|
|
||||||
|
COPY --from=const-build /scripts/devnet-consts.json wormchain/contracts/tools/
|
||||||
|
|
18
Tiltfile
18
Tiltfile
|
@ -756,6 +756,12 @@ if wormchain:
|
||||||
ignore = ["./wormchain/testing", "./wormchain/ts-sdk", "./wormchain/design", "./wormchain/vue", "./wormchain/build/wormchaind"],
|
ignore = ["./wormchain/testing", "./wormchain/ts-sdk", "./wormchain/design", "./wormchain/vue", "./wormchain/build/wormchaind"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
docker_build(
|
||||||
|
ref = "wormchain-deploy",
|
||||||
|
context = "./wormchain/contracts",
|
||||||
|
dockerfile = "./cosmwasm/Dockerfile.deploy",
|
||||||
|
)
|
||||||
|
|
||||||
def build_wormchain_yaml(yaml_path, num_instances):
|
def build_wormchain_yaml(yaml_path, num_instances):
|
||||||
wormchain_yaml = read_yaml_stream(yaml_path)
|
wormchain_yaml = read_yaml_stream(yaml_path)
|
||||||
|
|
||||||
|
@ -795,6 +801,7 @@ if wormchain:
|
||||||
else:
|
else:
|
||||||
k8s_yaml_with_ns(wormchain_path)
|
k8s_yaml_with_ns(wormchain_path)
|
||||||
|
|
||||||
|
|
||||||
k8s_resource(
|
k8s_resource(
|
||||||
"wormchain",
|
"wormchain",
|
||||||
port_forwards = [
|
port_forwards = [
|
||||||
|
@ -802,7 +809,14 @@ if wormchain:
|
||||||
port_forward(9090, container_port = 9090, name = "GRPC", host = webHost),
|
port_forward(9090, container_port = 9090, name = "GRPC", host = webHost),
|
||||||
port_forward(26659, container_port = 26657, name = "TENDERMINT [:26659]", host = webHost)
|
port_forward(26659, container_port = 26657, name = "TENDERMINT [:26659]", host = webHost)
|
||||||
],
|
],
|
||||||
resource_deps = [],
|
resource_deps = ["const-gen"],
|
||||||
|
labels = ["wormchain"],
|
||||||
|
trigger_mode = trigger_mode,
|
||||||
|
)
|
||||||
|
|
||||||
|
k8s_resource(
|
||||||
|
"wormchain-deploy",
|
||||||
|
resource_deps = ["wormchain"],
|
||||||
labels = ["wormchain"],
|
labels = ["wormchain"],
|
||||||
trigger_mode = trigger_mode,
|
trigger_mode = trigger_mode,
|
||||||
)
|
)
|
||||||
|
@ -823,7 +837,7 @@ if ibc_relayer:
|
||||||
port_forwards = [
|
port_forwards = [
|
||||||
port_forward(7597, name = "HTTPDEBUG [:7597]", host = webHost),
|
port_forward(7597, name = "HTTPDEBUG [:7597]", host = webHost),
|
||||||
],
|
],
|
||||||
resource_deps = ["guardian-validator", "terra2-terrad"],
|
resource_deps = ["wormchain", "terra2-terrad"],
|
||||||
labels = ["ibc-relayer"],
|
labels = ["ibc-relayer"],
|
||||||
trigger_mode = trigger_mode,
|
trigger_mode = trigger_mode,
|
||||||
)
|
)
|
||||||
|
|
|
@ -222,8 +222,6 @@ const contract_registrations = {
|
||||||
process.env.REGISTER_TERRA_TOKEN_BRIDGE_VAA,
|
process.env.REGISTER_TERRA_TOKEN_BRIDGE_VAA,
|
||||||
// NEAR
|
// NEAR
|
||||||
process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA,
|
process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA,
|
||||||
// Wormhole Chain
|
|
||||||
process.env.REGISTER_WORMCHAIN_TOKEN_BRIDGE_VAA,
|
|
||||||
// APTOS
|
// APTOS
|
||||||
process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA,
|
process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA,
|
||||||
],
|
],
|
||||||
|
|
|
@ -59,7 +59,7 @@ spec:
|
||||||
- key: wormchainKey0
|
- key: wormchainKey0
|
||||||
path: wormchainKey0
|
path: wormchainKey0
|
||||||
- key: wormchainKey1
|
- key: wormchainKey1
|
||||||
path: wormchainKey1
|
path: wormchainKey1
|
||||||
containers:
|
containers:
|
||||||
- name: guardiand
|
- name: guardiand
|
||||||
image: guardiand-image
|
image: guardiand-image
|
||||||
|
@ -104,19 +104,19 @@ spec:
|
||||||
- --neonRPC
|
- --neonRPC
|
||||||
- ws://eth-devnet:8545
|
- ws://eth-devnet:8545
|
||||||
# - --wormchainWS
|
# - --wormchainWS
|
||||||
# - ws://guardian-validator:26657/websocket
|
# - ws://wormchain:26657/websocket
|
||||||
# - --wormchainLCD
|
# - --wormchainLCD
|
||||||
# - http://guardian-validator:1317
|
# - http://wormchain:1317
|
||||||
# - --wormchainURL
|
# - --wormchainURL
|
||||||
# - guardian-validator:9090
|
# - wormchain:9090
|
||||||
# - --wormchainKeyPath
|
# - --wormchainKeyPath
|
||||||
# - /tmp/mounted-keys/wormchain/wormchainKey
|
# - /tmp/mounted-keys/wormchain/wormchainKey
|
||||||
# - --wormchainKeyPassPhrase
|
# - --wormchainKeyPassPhrase
|
||||||
# - test0000
|
# - test0000
|
||||||
# - --accountantWS
|
# - --accountantWS
|
||||||
# - http://guardian-validator:26657
|
# - http://wormchain:26657
|
||||||
# - --accountantContract
|
# - --accountantContract
|
||||||
# - wormhole1466nf3zuxpya8q9emxukd7vftaf6h4psr0a07srl5zw74zh84yjq4lyjmh
|
# - wormhole1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq0kdhcj
|
||||||
# - --accountantCheckEnabled=true
|
# - --accountantCheckEnabled=true
|
||||||
# - --terraWS
|
# - --terraWS
|
||||||
# - ws://terra-terrad:26657/websocket
|
# - ws://terra-terrad:26657/websocket
|
||||||
|
@ -199,5 +199,5 @@ metadata:
|
||||||
name: node-wormchain-key
|
name: node-wormchain-key
|
||||||
type: Opaque
|
type: Opaque
|
||||||
data:
|
data:
|
||||||
wormchainKey0: LS0tLS1CRUdJTiBURU5ERVJNSU5UIFBSSVZBVEUgS0VZLS0tLS0Ka2RmOiBiY3J5cHQKc2FsdDogNDc2ODc2NkE3OEZEN0ZBQjMwMUJGOTM5MUYwQ0Y2M0YKdHlwZTogc2VjcDI1NmsxCgpkbEZuN1ZqRk02RnJjYkdaVDRWeE5yRlE3SUhQS2RyVVBCRTYraW8yK0w0VFZqcis5emNIQTF3dzNubWtqNVFlCnVSekJWMjQyeUdTc3hNTTJZckI2Q1ZXdzlaWXJJY3JFeks1c0FuST0KPXB2aHkKLS0tLS1FTkQgVEVOREVSTUlOVCBQUklWQVRFIEtFWS0tLS0t
|
wormchainKey0: LS0tLS1CRUdJTiBURU5ERVJNSU5UIFBSSVZBVEUgS0VZLS0tLS0Ka2RmOiBiY3J5cHQKc2FsdDogNDc2ODc2NkE3OEZEN0ZBQjMwMUJGOTM5MUYwQ0Y2M0YKdHlwZTogc2VjcDI1NmsxCgpkbEZuN1ZqRk02RnJjYkdaVDRWeE5yRlE3SUhQS2RyVVBCRTYraW8yK0w0VFZqcis5emNIQTF3dzNubWtqNVFlCnVSekJWMjQyeUdTc3hNTTJZckI2Q1ZXdzlaWXJJY3JFeks1c0FuST0KPXB2aHkKLS0tLS1FTkQgVEVOREVSTUlOVCBQUklWQVRFIEtFWS0tLS0t
|
||||||
wormchainKey1: LS0tLS1CRUdJTiBURU5ERVJNSU5UIFBSSVZBVEUgS0VZLS0tLS0Ka2RmOiBiY3J5cHQKc2FsdDogMjMyRTU2NDMyMjBBNTcwRkVEQjFFMTFFOTNFM0E4NEIKdHlwZTogc2VjcDI1NmsxCgpBZjJ3aXNLdlBDOW4vaExYcDZaS1k5S091aVNYZG1lb3VvSzd3QVJ3cmNtTDV3MGs0YjFDSE5xTEp3ZXU1OEFGCkdTWGJsU3oySzNuWEl1V2hJZWtSNXE5WGRuUko4cGhSRWltbFNZST0KPU1vY1QKLS0tLS1FTkQgVEVOREVSTUlOVCBQUklWQVRFIEtFWS0tLS0tCg==
|
wormchainKey1: LS0tLS1CRUdJTiBURU5ERVJNSU5UIFBSSVZBVEUgS0VZLS0tLS0Ka2RmOiBiY3J5cHQKc2FsdDogMjMyRTU2NDMyMjBBNTcwRkVEQjFFMTFFOTNFM0E4NEIKdHlwZTogc2VjcDI1NmsxCgpBZjJ3aXNLdlBDOW4vaExYcDZaS1k5S091aVNYZG1lb3VvSzd3QVJ3cmNtTDV3MGs0YjFDSE5xTEp3ZXU1OEFGCkdTWGJsU3oySzNuWEl1V2hJZWtSNXE5WGRuUko4cGhSRWltbFNZST0KPU1vY1QKLS0tLS1FTkQgVEVOREVSTUlOVCBQUklWQVRFIEtFWS0tLS0tCg==
|
||||||
|
|
|
@ -90,5 +90,40 @@ spec:
|
||||||
httpGet:
|
httpGet:
|
||||||
port: 26657
|
port: 26657
|
||||||
path: /
|
path: /
|
||||||
|
periodSeconds: 1
|
||||||
|
restartPolicy: Always
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: wormchain-deploy
|
||||||
|
name: wormchain-deploy
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: wormchain-deploy
|
||||||
|
replicas: 1
|
||||||
|
updateStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: wormchain-deploy
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: wormchain-deploy
|
||||||
|
image: wormchain-deploy
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- "npm run deploy-wormchain --prefix=/app/tools && touch /app/tools/success && sleep infinity"
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- test
|
||||||
|
- -e
|
||||||
|
- "/app/tools/success"
|
||||||
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
|
|
|
@ -14,7 +14,6 @@ const terra2TokenBridgeVAA = process.env.REGISTER_TERRA2_TOKEN_BRIDGE_VAA;
|
||||||
const bscTokenBridgeVAA = process.env.REGISTER_BSC_TOKEN_BRIDGE_VAA;
|
const bscTokenBridgeVAA = process.env.REGISTER_BSC_TOKEN_BRIDGE_VAA;
|
||||||
const algoTokenBridgeVAA = process.env.REGISTER_ALGO_TOKEN_BRIDGE_VAA;
|
const algoTokenBridgeVAA = process.env.REGISTER_ALGO_TOKEN_BRIDGE_VAA;
|
||||||
const nearTokenBridgeVAA = process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA;
|
const nearTokenBridgeVAA = process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA;
|
||||||
const wormchainTokenBridgeVAA = process.env.REGISTER_WORMCHAIN_TOKEN_BRIDGE_VAA;
|
|
||||||
const aptosTokenBridgeVAA = process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA;
|
const aptosTokenBridgeVAA = process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA;
|
||||||
|
|
||||||
module.exports = async function(callback) {
|
module.exports = async function(callback) {
|
||||||
|
@ -91,16 +90,6 @@ module.exports = async function(callback) {
|
||||||
gasLimit: 2000000,
|
gasLimit: 2000000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register the wormhole token bridge endpoint
|
|
||||||
console.log("Registering Wormchain...");
|
|
||||||
await tokenBridge.methods
|
|
||||||
.registerChain("0x" + wormchainTokenBridgeVAA)
|
|
||||||
.send({
|
|
||||||
value: 0,
|
|
||||||
from: accounts[0],
|
|
||||||
gasLimit: 2000000,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register the APTOS endpoint
|
// Register the APTOS endpoint
|
||||||
console.log("Registering Aptos...");
|
console.log("Registering Aptos...");
|
||||||
await tokenBridge.methods.registerChain("0x" + aptosTokenBridgeVAA).send({
|
await tokenBridge.methods.registerChain("0x" + aptosTokenBridgeVAA).send({
|
||||||
|
|
|
@ -34,7 +34,7 @@ func main() {
|
||||||
|
|
||||||
wormchainURL := string("localhost:9090")
|
wormchainURL := string("localhost:9090")
|
||||||
wormchainKeyPath := string("./dev.wormchain.key")
|
wormchainKeyPath := string("./dev.wormchain.key")
|
||||||
contract := "wormhole1466nf3zuxpya8q9emxukd7vftaf6h4psr0a07srl5zw74zh84yjq4lyjmh"
|
contract := "wormhole1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq0kdhcj"
|
||||||
guardianKeyPath := string("./dev.guardian.key")
|
guardianKeyPath := string("./dev.guardian.key")
|
||||||
|
|
||||||
wormchainKey, err := wormconn.LoadWormchainPrivKey(wormchainKeyPath, "test0000")
|
wormchainKey, err := wormconn.LoadWormchainPrivKey(wormchainKeyPath, "test0000")
|
||||||
|
|
|
@ -238,12 +238,61 @@
|
||||||
"3104": {
|
"3104": {
|
||||||
"rpcUrlTilt": "http://wormchain:1317",
|
"rpcUrlTilt": "http://wormchain:1317",
|
||||||
"rpcUrlLocal": "http://localhost:1319",
|
"rpcUrlLocal": "http://localhost:1319",
|
||||||
"rpcPort": "1319",
|
"tendermintUrlTilt": "http://wormchain:26657",
|
||||||
|
"tendermintUrlLocal": "http://localhost:26659",
|
||||||
|
"rpcPort": "1317",
|
||||||
|
"tendermintPort": "26657",
|
||||||
"contracts": {
|
"contracts": {
|
||||||
"coreEmitterAddress": "wormhole1ap5vgur5zlgys8whugfegnn43emka567dtq0jl",
|
"accountingNativeAddress": "wormhole1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq0kdhcj"
|
||||||
"coreNativeAddress": "wormhole1ap5vgur5zlgys8whugfegnn43emka567dtq0jl",
|
},
|
||||||
"tokenBridgeEmitterAddress": "wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z",
|
"accounts": {
|
||||||
"tokenBridgeNativeAddress": "wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z"
|
"wormchainNodeOfGuardian0": {
|
||||||
|
"address": "C10820983F33456CE7BEB3A046F5A83FA34F027D",
|
||||||
|
"addressBase64": "wQggmD8zRWznvrOgRvWoP6NPAn0=",
|
||||||
|
"addressWormhole": "000000000000000000000000c10820983f33456ce7beb3a046f5a83fa34f027d",
|
||||||
|
"public": "wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq",
|
||||||
|
"privateHex": "48d23cc417a30674e907a2403f109f082d92e197823d02e6a423c6aeb8e41204",
|
||||||
|
"cosmos.crypto.secp256k1.PubKey": "AuwYyCUBxQiBGSUWebU46c+OrlApVsyGLHd4qhSDZeiG",
|
||||||
|
"tendermint/PrivKeyEd25519": "DONGe0wxovG1ZuCQ1iMbyBCW/hG5UeKz6ZFfhdZYznRSC48Lc1nwhUwXzHtXfwAOY0mO3mhTy4CMwPeYFvBZ1A==",
|
||||||
|
"mnemonic": "notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius"
|
||||||
|
},
|
||||||
|
"wormchainValidator0": {
|
||||||
|
"public": "wormholevaloper1cyyzpxplxdzkeea7kwsydadg87357qna87hzv8",
|
||||||
|
"tendermint/PubKeyEd25519": "fnfoo/C+i+Ng1J8vct6wfvrTS9JeNIG5UeO87ZHKMkY=",
|
||||||
|
"tendermint/PrivKeyEd25519": "Zb3gQZSd8qNMyXUQdKmeqM/SSYeVDD80S4XPEsCAgPN+d+ij8L6L42DUny9y3rB++tNL0l40gblR47ztkcoyRg=="
|
||||||
|
},
|
||||||
|
"wormchainNodeOfGuardian1": {
|
||||||
|
"address": "701C475B19A3F68D3FDEBF09591487FACEF2D636",
|
||||||
|
"addressWormhole": "000000000000000000000000701c475b19a3f68d3fdebf09591487facef2d636",
|
||||||
|
"addressBase64": "cBxHWxmj9o0/3r8JWRSH+s7y1jY=",
|
||||||
|
"public": "wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr",
|
||||||
|
"privateHex": "7095b73fa951fd117d54f3bca130b8088625db2d60d94d4f064791dc1a792b29",
|
||||||
|
"cosmos.crypto.secp256k1.PubKey": "ApJi/CY2RGyzA5cQtDwU9c+o7T8OE+SjrgcG5PwLMjTP",
|
||||||
|
"tendermint/PrivKeyEd25519": "TTdzb3XLJbSXP/5VhzPJCWysCDDH2hEXTqdvLI6RYk7rxPwzCXTprp2ZEfSCfQswYgUUQgO9JKzbAtfyeK2G1A==",
|
||||||
|
"mnemonic": "maple pudding enjoy pole real rabbit soft make square city wrestle area aisle dwarf spike voice over still post lend genius bitter exit shoot"
|
||||||
|
},
|
||||||
|
"wormchainValidator1": {
|
||||||
|
"public": "wormholevaloper1wqwywkce50mg6077huy4j9y8lt80943kxgr79y",
|
||||||
|
"tendermint/PubKeyEd25519": "Zcujkt1sXRWWLfhgxLAm/Q+ioLn4wFim0OnGPLlCG0I=",
|
||||||
|
"tendermint/PrivKeyEd25519": "SGWIYI3BgC/dxNOk1gYx6LpChAKqWGtAfZSx0SDFWuhly6OS3WxdFZYt+GDEsCb9D6KgufjAWKbQ6cY8uUIbQg=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"addresses": {
|
||||||
|
"native": {
|
||||||
|
"address": "uworm",
|
||||||
|
"addressWormhole": "010c0ded78f1b69ec7b79b9ee592fbbcacebc97db1c695220a833135bfa74824",
|
||||||
|
"denom": "uworm",
|
||||||
|
"name": "worm",
|
||||||
|
"symbol": "worm",
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"testToken": {
|
||||||
|
"address": "wormhole1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqhnev3f",
|
||||||
|
"addressWormhole": "003f822e9066cfea09b9ce1247e8f79a86a24dda2d8b3d76a608ae7583220411",
|
||||||
|
"name": "MOCK",
|
||||||
|
"symbol": "MCK",
|
||||||
|
"decimals": 6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"22": {
|
"22": {
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# copy devnet-consts.json to chain dirs for local use, so we can keep docker
|
||||||
|
# build contexts scoped to the chain, rather than the root just to read this file.
|
||||||
|
file="./scripts/devnet-consts.json"
|
||||||
|
paths=(
|
||||||
|
./terra2/tools/
|
||||||
|
./wormchain/contracts/tools/
|
||||||
|
)
|
||||||
|
|
||||||
|
for dest in "${paths[@]}"; do
|
||||||
|
dirname=$(dirname $dest)
|
||||||
|
if [[ -d "$dirname" ]]; then
|
||||||
|
echo "copying $file to $dest"
|
||||||
|
cp $file $dest
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "distribute devnet consts complete!"
|
|
@ -90,7 +90,6 @@ bscTokenBridge=$(jq --raw-output '.chains."4".contracts.tokenBridgeEmitterAddres
|
||||||
algoTokenBridge=$(jq --raw-output '.chains."8".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
algoTokenBridge=$(jq --raw-output '.chains."8".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
||||||
nearTokenBridge=$(jq --raw-output '.chains."15".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
nearTokenBridge=$(jq --raw-output '.chains."15".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
||||||
terra2TokenBridge=$(jq --raw-output '.chains."18".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
terra2TokenBridge=$(jq --raw-output '.chains."18".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
||||||
wormchainTokenBridge=$(jq --raw-output '.chains."3104".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
|
||||||
aptosTokenBridge=$(jq --raw-output '.chains."22".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
aptosTokenBridge=$(jq --raw-output '.chains."22".contracts.tokenBridgeEmitterAddress' $addressesJson)
|
||||||
|
|
||||||
solNFTBridge=$(jq --raw-output '.chains."1".contracts.nftBridgeEmitterAddress' $addressesJson)
|
solNFTBridge=$(jq --raw-output '.chains."1".contracts.nftBridgeEmitterAddress' $addressesJson)
|
||||||
|
@ -108,7 +107,6 @@ bscTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m Tok
|
||||||
algoTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c algorand -a ${algoTokenBridge} -g ${guardiansPrivateCSV})
|
algoTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c algorand -a ${algoTokenBridge} -g ${guardiansPrivateCSV})
|
||||||
nearTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c near -a ${nearTokenBridge} -g ${guardiansPrivateCSV})
|
nearTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c near -a ${nearTokenBridge} -g ${guardiansPrivateCSV})
|
||||||
terra2TokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c terra2 -a ${terra2TokenBridge} -g ${guardiansPrivateCSV})
|
terra2TokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c terra2 -a ${terra2TokenBridge} -g ${guardiansPrivateCSV})
|
||||||
wormchainTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c wormchain -a ${wormchainTokenBridge} -g ${guardiansPrivateCSV})
|
|
||||||
aptosTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c aptos -a ${aptosTokenBridge} -g ${guardiansPrivateCSV})
|
aptosTokenBridgeVAA=$(node ./clients/js/build/main.js generate registration -m TokenBridge -c aptos -a ${aptosTokenBridge} -g ${guardiansPrivateCSV})
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,7 +129,6 @@ bscTokenBridge="REGISTER_BSC_TOKEN_BRIDGE_VAA"
|
||||||
algoTokenBridge="REGISTER_ALGO_TOKEN_BRIDGE_VAA"
|
algoTokenBridge="REGISTER_ALGO_TOKEN_BRIDGE_VAA"
|
||||||
terra2TokenBridge="REGISTER_TERRA2_TOKEN_BRIDGE_VAA"
|
terra2TokenBridge="REGISTER_TERRA2_TOKEN_BRIDGE_VAA"
|
||||||
nearTokenBridge="REGISTER_NEAR_TOKEN_BRIDGE_VAA"
|
nearTokenBridge="REGISTER_NEAR_TOKEN_BRIDGE_VAA"
|
||||||
wormchainTokenBridge="REGISTER_WORMCHAIN_TOKEN_BRIDGE_VAA"
|
|
||||||
aptosTokenBridge="REGISTER_APTOS_TOKEN_BRIDGE_VAA"
|
aptosTokenBridge="REGISTER_APTOS_TOKEN_BRIDGE_VAA"
|
||||||
|
|
||||||
solNFTBridge="REGISTER_SOL_NFT_BRIDGE_VAA"
|
solNFTBridge="REGISTER_SOL_NFT_BRIDGE_VAA"
|
||||||
|
@ -193,10 +190,6 @@ upsert_env_file $envFile $nearTokenBridge $nearTokenBridgeVAA
|
||||||
upsert_env_file $ethFile $nearNFTBridge $nearNFTBridgeVAA
|
upsert_env_file $ethFile $nearNFTBridge $nearNFTBridgeVAA
|
||||||
upsert_env_file $envFile $nearNFTBridge $nearNFTBridgeVAA
|
upsert_env_file $envFile $nearNFTBridge $nearNFTBridgeVAA
|
||||||
|
|
||||||
# wormchain token bridge
|
|
||||||
upsert_env_file $ethFile $wormchainTokenBridge $wormchainTokenBridgeVAA
|
|
||||||
upsert_env_file $envFile $wormchainTokenBridge $wormchainTokenBridgeVAA
|
|
||||||
|
|
||||||
# 7) copy the local .env file to the solana & terra dirs, if the script is running on the host machine
|
# 7) copy the local .env file to the solana & terra dirs, if the script is running on the host machine
|
||||||
# chain dirs will not exist if running in docker for Tilt, only if running locally. check before copying.
|
# chain dirs will not exist if running in docker for Tilt, only if running locally. check before copying.
|
||||||
# copy ethFile to ethereum
|
# copy ethFile to ethereum
|
||||||
|
@ -212,6 +205,7 @@ paths=(
|
||||||
./solana/.env
|
./solana/.env
|
||||||
./terra/tools/.env
|
./terra/tools/.env
|
||||||
./cosmwasm/deployment/terra2/tools/.env
|
./cosmwasm/deployment/terra2/tools/.env
|
||||||
|
./wormchain/contracts/tools/.env
|
||||||
)
|
)
|
||||||
|
|
||||||
for envDest in "${paths[@]}"; do
|
for envDest in "${paths[@]}"; do
|
||||||
|
|
|
@ -538,8 +538,8 @@ const DEVNET = {
|
||||||
nft_bridge: undefined,
|
nft_bridge: undefined,
|
||||||
},
|
},
|
||||||
wormchain: {
|
wormchain: {
|
||||||
core: "wormhole1ap5vgur5zlgys8whugfegnn43emka567dtq0jl",
|
core: "wormhole14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9srrg465",
|
||||||
token_bridge: "wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z",
|
token_bridge: "wormhole1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq0kdhcj",
|
||||||
nft_bridge: undefined,
|
nft_bridge: undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -274,8 +274,6 @@ const contract_registrations = {
|
||||||
process.env.REGISTER_TERRA2_TOKEN_BRIDGE_VAA,
|
process.env.REGISTER_TERRA2_TOKEN_BRIDGE_VAA,
|
||||||
// NEAR
|
// NEAR
|
||||||
process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA,
|
process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA,
|
||||||
// Wormhole Chain
|
|
||||||
process.env.REGISTER_WORMCHAIN_TOKEN_BRIDGE_VAA,
|
|
||||||
// APTOS
|
// APTOS
|
||||||
process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA,
|
process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA,
|
||||||
],
|
],
|
||||||
|
|
|
@ -14,6 +14,7 @@ devnet/wormchain-*/config/addrbook.json
|
||||||
devnet/wormchain-*/config/genesis.json
|
devnet/wormchain-*/config/genesis.json
|
||||||
ts-sdk/node_modules
|
ts-sdk/node_modules
|
||||||
ts-sdk/lib
|
ts-sdk/lib
|
||||||
|
contracts/artifacts
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
*.iml
|
*.iml
|
||||||
|
|
|
@ -43,6 +43,31 @@ ts-sdk: vue
|
||||||
run: build/wormchaind
|
run: build/wormchaind
|
||||||
./$< start --home build --log_level="debug"
|
./$< start --home build --log_level="debug"
|
||||||
|
|
||||||
|
# get npm packages for contracts/tools
|
||||||
|
contracts-tools-deps: contracts/tools/package-lock.json
|
||||||
|
npm ci --prefix=contracts/tools
|
||||||
|
|
||||||
|
# get .env and devnet-consts.json for contracts/tools
|
||||||
|
contracts-devnet-env:
|
||||||
|
cd .. && ./scripts/guardian-set-init.sh 1
|
||||||
|
cd .. && ./scripts/distribute-devnet-consts.sh
|
||||||
|
|
||||||
|
# get wasm artifacts for cosmwasm contracts
|
||||||
|
contracts-artifacts:
|
||||||
|
cd ../cosmwasm && $(MAKE) artifacts
|
||||||
|
cp -r ../cosmwasm/artifacts contracts
|
||||||
|
|
||||||
|
# get everything needed to
|
||||||
|
contracts-deploy-setup: contracts-tools-deps contracts-devnet-env contracts-artifacts
|
||||||
|
|
||||||
|
# runs the contract deployment script
|
||||||
|
contracts-deploy-local: contracts-deploy-setup
|
||||||
|
npm run deploy-wormchain --prefix=contracts/tools
|
||||||
|
|
||||||
|
# starts wormchaind in a container, deploys contracts, tests contract interaction
|
||||||
|
contracts-deploy-test: client contracts-deploy-setup
|
||||||
|
./contracts/run_deploy_test.sh
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
go test -v ./...
|
go test -v ./...
|
||||||
|
|
|
@ -1,58 +1,208 @@
|
||||||
halt-height = 0
|
# Cosmos Node config
|
||||||
halt-time = 0
|
|
||||||
index-events = []
|
###############################################################################
|
||||||
inter-block-cache = true
|
### Base Configuration ###
|
||||||
min-retain-blocks = 0
|
###############################################################################
|
||||||
minimum-gas-prices = "0stake"
|
|
||||||
pruning = "default"
|
|
||||||
pruning-interval = "0"
|
|
||||||
pruning-keep-every = "0"
|
|
||||||
pruning-keep-recent = "0"
|
|
||||||
chain-id = "wormchain"
|
chain-id = "wormchain"
|
||||||
|
|
||||||
[api]
|
# The minimum gas prices a validator is willing to accept for processing a
|
||||||
address = "tcp://localhost:1317"
|
# transaction. A transaction's fees must meet the minimum of any denomination
|
||||||
enable = true
|
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||||
enabled-unsafe-cors = true
|
minimum-gas-prices = "0uworm"
|
||||||
max-open-connections = 1000
|
|
||||||
rpc-max-body-bytes = 1000000
|
|
||||||
rpc-read-timeout = 10
|
|
||||||
rpc-write-timeout = 0
|
|
||||||
swagger = false
|
|
||||||
|
|
||||||
[grpc]
|
# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
|
||||||
address = "0.0.0.0:9090"
|
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||||
enable = true
|
# everything: all saved states will be deleted, storing only the current and previous state; pruning at 10 block intervals
|
||||||
|
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
|
||||||
|
pruning = "default"
|
||||||
|
|
||||||
[grpc-web]
|
# These are applied if and only if the pruning strategy is custom.
|
||||||
address = "0.0.0.0:9091"
|
pruning-keep-recent = "0"
|
||||||
enable = true
|
pruning-keep-every = "0"
|
||||||
enable-unsafe-cors = false
|
pruning-interval = "0"
|
||||||
|
|
||||||
[rosetta]
|
# HaltHeight contains a non-zero block height at which a node will gracefully
|
||||||
address = ":8080"
|
# halt and shutdown that can be used to assist upgrades and testing.
|
||||||
blockchain = "app"
|
#
|
||||||
enable = false
|
# Note: Commitment of state will be attempted on the corresponding block.
|
||||||
network = "network"
|
halt-height = 0
|
||||||
offline = false
|
|
||||||
retries = 3
|
|
||||||
|
|
||||||
[rpc]
|
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
|
||||||
cors_allowed_origins = ["*"]
|
# a node will gracefully halt and shutdown that can be used to assist upgrades
|
||||||
|
# and testing.
|
||||||
|
#
|
||||||
|
# Note: Commitment of state will be attempted on the corresponding block.
|
||||||
|
halt-time = 0
|
||||||
|
|
||||||
[state-sync]
|
# MinRetainBlocks defines the minimum block height offset from the current
|
||||||
snapshot-interval = 0
|
# block being committed, such that all blocks past this offset are pruned
|
||||||
snapshot-keep-recent = 2
|
# from Tendermint. It is used as part of the process of determining the
|
||||||
|
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
|
||||||
|
# that no blocks should be pruned.
|
||||||
|
#
|
||||||
|
# This configuration value is only responsible for pruning Tendermint blocks.
|
||||||
|
# It has no bearing on application state pruning which is determined by the
|
||||||
|
# "pruning-*" configurations.
|
||||||
|
#
|
||||||
|
# Note: Tendermint block pruning is dependant on this parameter in conunction
|
||||||
|
# with the unbonding (safety threshold) period, state pruning and state sync
|
||||||
|
# snapshot parameters to determine the correct minimum value of
|
||||||
|
# ResponseCommit.RetainHeight.
|
||||||
|
min-retain-blocks = 0
|
||||||
|
|
||||||
|
# InterBlockCache enables inter-block caching.
|
||||||
|
inter-block-cache = true
|
||||||
|
|
||||||
|
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
|
||||||
|
# which informs Tendermint what to index. If empty, all events will be indexed.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# ["message.sender", "message.recipient"]
|
||||||
|
index-events = []
|
||||||
|
|
||||||
|
# IavlCacheSize set the size of the iavl tree cache.
|
||||||
|
# Default cache size is 50mb.
|
||||||
|
iavl-cache-size = 781250
|
||||||
|
|
||||||
|
# IAVLDisableFastNode enables or disables the fast node feature of IAVL.
|
||||||
|
# Default is true.
|
||||||
|
iavl-disable-fastnode = true
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### Telemetry Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
[telemetry]
|
[telemetry]
|
||||||
enable-hostname = false
|
|
||||||
enable-hostname-label = false
|
# Prefixed with keys to separate services.
|
||||||
enable-service-label = false
|
service-name = ""
|
||||||
enabled = false
|
|
||||||
global-labels = []
|
# Enabled enables the application telemetry functionality. When enabled,
|
||||||
prometheus-retention-time = 0
|
# an in-memory sink is also enabled by default. Operators may also enabled
|
||||||
service-name = ""
|
# other sinks such as Prometheus.
|
||||||
|
enabled = false
|
||||||
|
|
||||||
|
# Enable prefixing gauge values with hostname.
|
||||||
|
enable-hostname = false
|
||||||
|
|
||||||
|
# Enable adding hostname to labels.
|
||||||
|
enable-hostname-label = false
|
||||||
|
|
||||||
|
# Enable adding service to labels.
|
||||||
|
enable-service-label = false
|
||||||
|
|
||||||
|
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
|
||||||
|
prometheus-retention-time = 0
|
||||||
|
|
||||||
|
# GlobalLabels defines a global set of name/value label tuples applied to all
|
||||||
|
# metrics emitted using the wrapper functions defined in telemetry package.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# [["chain_id", "cosmoshub-1"]]
|
||||||
|
global-labels = [
|
||||||
|
]
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### API Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
[api]
|
||||||
|
|
||||||
|
# Enable defines if the API server should be enabled.
|
||||||
|
enable = true
|
||||||
|
|
||||||
|
# Swagger defines if swagger documentation should automatically be registered.
|
||||||
|
swagger = false
|
||||||
|
|
||||||
|
# Address defines the API server to listen on.
|
||||||
|
address = "tcp://0.0.0.0:1317"
|
||||||
|
|
||||||
|
# MaxOpenConnections defines the number of maximum open connections.
|
||||||
|
max-open-connections = 1000
|
||||||
|
|
||||||
|
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
|
||||||
|
rpc-read-timeout = 10
|
||||||
|
|
||||||
|
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
|
||||||
|
rpc-write-timeout = 0
|
||||||
|
|
||||||
|
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
|
||||||
|
rpc-max-body-bytes = 1000000
|
||||||
|
|
||||||
|
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||||
|
enabled-unsafe-cors = true
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### Rosetta Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
[rosetta]
|
||||||
|
|
||||||
|
# Enable defines if the Rosetta API server should be enabled.
|
||||||
|
enable = false
|
||||||
|
|
||||||
|
# Address defines the Rosetta API server to listen on.
|
||||||
|
address = ":8080"
|
||||||
|
|
||||||
|
# Network defines the name of the blockchain that will be returned by Rosetta.
|
||||||
|
blockchain = "app"
|
||||||
|
|
||||||
|
# Network defines the name of the network that will be returned by Rosetta.
|
||||||
|
network = "network"
|
||||||
|
|
||||||
|
# Retries defines the number of retries when connecting to the node before failing.
|
||||||
|
retries = 3
|
||||||
|
|
||||||
|
# Offline defines if Rosetta server should run in offline mode.
|
||||||
|
offline = false
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### gRPC Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
[grpc]
|
||||||
|
|
||||||
|
# Enable defines if the gRPC server should be enabled.
|
||||||
|
enable = true
|
||||||
|
|
||||||
|
# Address defines the gRPC server address to bind to.
|
||||||
|
address = "0.0.0.0:9090"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### gRPC Web Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
[grpc-web]
|
||||||
|
|
||||||
|
# GRPCWebEnable defines if the gRPC-web should be enabled.
|
||||||
|
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
|
||||||
|
enable = true
|
||||||
|
|
||||||
|
# Address defines the gRPC-web server address to bind to.
|
||||||
|
address = "0.0.0.0:9091"
|
||||||
|
|
||||||
|
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||||
|
enable-unsafe-cors = true
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### State Sync Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
|
||||||
|
# blocks, instead downloading and applying a snapshot of the application state at a given height.
|
||||||
|
[state-sync]
|
||||||
|
|
||||||
|
# snapshot-interval specifies the block interval at which local state sync snapshots are
|
||||||
|
# taken (0 to disable). Must be a multiple of pruning-keep-every.
|
||||||
|
snapshot-interval = 0
|
||||||
|
|
||||||
|
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
|
||||||
|
snapshot-keep-recent = 2
|
||||||
|
|
||||||
[wasm]
|
[wasm]
|
||||||
lru_size = 0
|
# This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries
|
||||||
query_gas_limit = 300000
|
query_gas_limit = 300000
|
||||||
|
# This is the number of wasm vm instances we keep cached in memory for speed-up
|
||||||
|
# Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally
|
||||||
|
lru_size = 0
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
broadcast-mode = "block"
|
# Tendermint client config
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
### Client Configuration ###
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# The network chain ID
|
||||||
chain-id = "wormchain"
|
chain-id = "wormchain"
|
||||||
|
# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory)
|
||||||
keyring-backend = "test"
|
keyring-backend = "test"
|
||||||
node = "tcp://localhost:26657"
|
# CLI output format (text|json)
|
||||||
output = "text"
|
output = "text"
|
||||||
|
# <host>:<port> to Tendermint RPC interface for this chain
|
||||||
|
node = "tcp://0.0.0.0:26657"
|
||||||
|
# Transaction broadcasting mode (sync|async|block)
|
||||||
|
broadcast-mode = "block"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
proxy_app = "tcp://127.0.0.1:26658"
|
proxy_app = "tcp://127.0.0.1:26658"
|
||||||
|
|
||||||
# A custom human readable name for this node
|
# A custom human readable name for this node
|
||||||
moniker = "mynode"
|
moniker = "wormchain-local"
|
||||||
|
|
||||||
# If this node is many blocks behind the tip of the chain, FastSync
|
# If this node is many blocks behind the tip of the chain, FastSync
|
||||||
# allows them to catchup quickly by downloading blocks in parallel
|
# allows them to catchup quickly by downloading blocks in parallel
|
||||||
|
@ -93,7 +93,7 @@ laddr = "tcp://0.0.0.0:26657"
|
||||||
# A list of origins a cross-domain request can be executed from
|
# A list of origins a cross-domain request can be executed from
|
||||||
# Default value '[]' disables cors support
|
# Default value '[]' disables cors support
|
||||||
# Use '["*"]' to allow any origin
|
# Use '["*"]' to allow any origin
|
||||||
cors_allowed_origins = ["*", ]
|
cors_allowed_origins = []
|
||||||
|
|
||||||
# A list of methods the client is allowed to use with cross-domain requests
|
# A list of methods the client is allowed to use with cross-domain requests
|
||||||
cors_allowed_methods = ["HEAD", "GET", "POST", ]
|
cors_allowed_methods = ["HEAD", "GET", "POST", ]
|
||||||
|
@ -136,6 +136,33 @@ max_subscription_clients = 100
|
||||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
# the estimated # maximum number of broadcast_tx_commit calls per block.
|
||||||
max_subscriptions_per_client = 5
|
max_subscriptions_per_client = 5
|
||||||
|
|
||||||
|
# Experimental parameter to specify the maximum number of events a node will
|
||||||
|
# buffer, per subscription, before returning an error and closing the
|
||||||
|
# subscription. Must be set to at least 100, but higher values will accommodate
|
||||||
|
# higher event throughput rates (and will use more memory).
|
||||||
|
experimental_subscription_buffer_size = 200
|
||||||
|
|
||||||
|
# Experimental parameter to specify the maximum number of RPC responses that
|
||||||
|
# can be buffered per WebSocket client. If clients cannot read from the
|
||||||
|
# WebSocket endpoint fast enough, they will be disconnected, so increasing this
|
||||||
|
# parameter may reduce the chances of them being disconnected (but will cause
|
||||||
|
# the node to use more memory).
|
||||||
|
#
|
||||||
|
# Must be at least the same as "experimental_subscription_buffer_size",
|
||||||
|
# otherwise connections could be dropped unnecessarily. This value should
|
||||||
|
# ideally be somewhat higher than "experimental_subscription_buffer_size" to
|
||||||
|
# accommodate non-subscription-related RPC responses.
|
||||||
|
experimental_websocket_write_buffer_size = 200
|
||||||
|
|
||||||
|
# If a WebSocket client cannot read fast enough, at present we may
|
||||||
|
# silently drop events instead of generating an error or disconnecting the
|
||||||
|
# client.
|
||||||
|
#
|
||||||
|
# Enabling this experimental parameter will cause the WebSocket connection to
|
||||||
|
# be closed instead if it cannot read fast enough, allowing for greater
|
||||||
|
# predictability in subscription behaviour.
|
||||||
|
experimental_close_on_slow_client = false
|
||||||
|
|
||||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
# How long to wait for a tx to be committed during /broadcast_tx_commit.
|
||||||
# WARNING: Using a value larger than 10s will result in increasing the
|
# WARNING: Using a value larger than 10s will result in increasing the
|
||||||
# global HTTP write timeout, which applies to all connections and endpoints.
|
# global HTTP write timeout, which applies to all connections and endpoints.
|
||||||
|
@ -245,6 +272,11 @@ dial_timeout = "3s"
|
||||||
#######################################################
|
#######################################################
|
||||||
[mempool]
|
[mempool]
|
||||||
|
|
||||||
|
# Mempool version to use:
|
||||||
|
# 1) "v0" - (default) FIFO mempool.
|
||||||
|
# 2) "v1" - prioritized mempool.
|
||||||
|
version = "v0"
|
||||||
|
|
||||||
recheck = true
|
recheck = true
|
||||||
broadcast = true
|
broadcast = true
|
||||||
wal_dir = ""
|
wal_dir = ""
|
||||||
|
@ -274,6 +306,22 @@ max_tx_bytes = 1048576
|
||||||
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
|
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
|
||||||
max_batch_bytes = 0
|
max_batch_bytes = 0
|
||||||
|
|
||||||
|
# ttl-duration, if non-zero, defines the maximum amount of time a transaction
|
||||||
|
# can exist for in the mempool.
|
||||||
|
#
|
||||||
|
# Note, if ttl-num-blocks is also defined, a transaction will be removed if it
|
||||||
|
# has existed in the mempool at least ttl-num-blocks number of blocks or if it's
|
||||||
|
# insertion time into the mempool is beyond ttl-duration.
|
||||||
|
ttl-duration = "0s"
|
||||||
|
|
||||||
|
# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction
|
||||||
|
# can exist for in the mempool.
|
||||||
|
#
|
||||||
|
# Note, if ttl-duration is also defined, a transaction will be removed if it
|
||||||
|
# has existed in the mempool at least ttl-num-blocks number of blocks or if
|
||||||
|
# it's insertion time into the mempool is beyond ttl-duration.
|
||||||
|
ttl-num-blocks = 0
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
### State Sync Configuration Options ###
|
### State Sync Configuration Options ###
|
||||||
#######################################################
|
#######################################################
|
||||||
|
@ -362,6 +410,16 @@ create_empty_blocks_interval = "0s"
|
||||||
peer_gossip_sleep_duration = "100ms"
|
peer_gossip_sleep_duration = "100ms"
|
||||||
peer_query_maj23_sleep_duration = "2s"
|
peer_query_maj23_sleep_duration = "2s"
|
||||||
|
|
||||||
|
#######################################################
|
||||||
|
### Storage Configuration Options ###
|
||||||
|
#######################################################
|
||||||
|
|
||||||
|
# Set to true to discard ABCI responses from the state store, which can save a
|
||||||
|
# considerable amount of disk space. Set to false to ensure ABCI responses are
|
||||||
|
# persisted. ABCI responses are required for /block_results RPC queries, and to
|
||||||
|
# reindex events in the command-line tool.
|
||||||
|
discard_abci_responses = false
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
### Transaction Indexer Configuration Options ###
|
### Transaction Indexer Configuration Options ###
|
||||||
#######################################################
|
#######################################################
|
||||||
|
@ -376,8 +434,14 @@ peer_query_maj23_sleep_duration = "2s"
|
||||||
# 1) "null"
|
# 1) "null"
|
||||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||||
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
|
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||||
|
# 3) "psql" - the indexer services backed by PostgreSQL.
|
||||||
|
# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||||
indexer = "kv"
|
indexer = "kv"
|
||||||
|
|
||||||
|
# The PostgreSQL connection configuration, the connection format:
|
||||||
|
# postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
|
||||||
|
psql-conn = ""
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
### Instrumentation Configuration Options ###
|
### Instrumentation Configuration Options ###
|
||||||
#######################################################
|
#######################################################
|
||||||
|
|
|
@ -65,7 +65,11 @@
|
||||||
"coins": [
|
"coins": [
|
||||||
{
|
{
|
||||||
"denom": "utest",
|
"denom": "utest",
|
||||||
"amount": "10000"
|
"amount": "100000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"denom": "uworm",
|
||||||
|
"amount": "1000000000"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -74,7 +78,11 @@
|
||||||
"coins": [
|
"coins": [
|
||||||
{
|
{
|
||||||
"denom": "utest",
|
"denom": "utest",
|
||||||
"amount": "20000"
|
"amount": "100000000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"denom": "uworm",
|
||||||
|
"amount": "200000000"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -380,4 +388,4 @@
|
||||||
"sequenceCounterList": []
|
"sequenceCounterList": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -exu pipefail
|
||||||
|
|
||||||
|
echo "Starting wormchaind"
|
||||||
|
./build/wormchaind start --home build --rpc.laddr="tcp://0.0.0.0:26659" > wormchaind.out 2>&1 &
|
||||||
|
# give wormchain 2 seconds to startup
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
echo "cleaning up test container"
|
||||||
|
# kill wormchain, any dependents of the process (just in case)
|
||||||
|
pkill -f "./build/wormchaind start --home build --rpc.laddr=tcp://0.0.0.0:26659"
|
||||||
|
pkill -P $$
|
||||||
|
# remove wormchaind log file
|
||||||
|
rm wormchaind.out
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_and_exit_failure() {
|
||||||
|
cleanup
|
||||||
|
echo "exiting with failure code"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# run the deploy, and catch if it returns an error code
|
||||||
|
npm run deploy-and-test --prefix contracts/tools || cleanup_and_exit_failure
|
||||||
|
|
||||||
|
# cleanup and return success
|
||||||
|
cleanup
|
|
@ -0,0 +1 @@
|
||||||
|
save-exact=true
|
|
@ -0,0 +1,206 @@
|
||||||
|
import "dotenv/config";
|
||||||
|
import * as os from "os"
|
||||||
|
import { SigningCosmWasmClient, InstantiateResult } from "@cosmjs/cosmwasm-stargate";
|
||||||
|
import { GasPrice } from "@cosmjs/stargate"
|
||||||
|
import { Secp256k1HdWallet } from "@cosmjs/amino";
|
||||||
|
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { readdirSync, } from "fs";
|
||||||
|
import * as util from 'util'
|
||||||
|
import { toUtf8 } from "@cosmjs/encoding";
|
||||||
|
|
||||||
|
import * as devnetConsts from "./devnet-consts.json"
|
||||||
|
|
||||||
|
if (process.env.INIT_SIGNERS === "undefined") {
|
||||||
|
let msg = `.env is missing. run "make contracts-tools-deps" to fetch.`
|
||||||
|
console.error(msg)
|
||||||
|
throw msg
|
||||||
|
}
|
||||||
|
|
||||||
|
const readFileAsync = util.promisify(fs.readFile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: Only append to this array: keeping the ordering is crucial, as the
|
||||||
|
contracts must be imported in a deterministic order so their addresses remain
|
||||||
|
deterministic.
|
||||||
|
*/
|
||||||
|
type ContractName = string
|
||||||
|
const artifacts: ContractName[] = [
|
||||||
|
"cw20_base.wasm",
|
||||||
|
"wormchain_accounting.wasm",
|
||||||
|
];
|
||||||
|
|
||||||
|
const ARTIFACTS_PATH = "../artifacts/"
|
||||||
|
/* Check that the artifact folder contains all the wasm files we expect and nothing else */
|
||||||
|
|
||||||
|
try {
|
||||||
|
const actual_artifacts = readdirSync(ARTIFACTS_PATH).filter((a) =>
|
||||||
|
a.endsWith(".wasm")
|
||||||
|
);
|
||||||
|
|
||||||
|
const missing_artifacts = artifacts.filter(
|
||||||
|
(a) => !actual_artifacts.includes(a)
|
||||||
|
);
|
||||||
|
if (missing_artifacts.length) {
|
||||||
|
console.log(
|
||||||
|
"Error during wormchain deployment. The following files are expected to be in the artifacts folder:"
|
||||||
|
);
|
||||||
|
missing_artifacts.forEach((file) => console.log(` - ${file}`));
|
||||||
|
console.log(
|
||||||
|
"Hint: the deploy script needs to run after the contracts have been built."
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"External binary blobs need to be manually added in tools/Dockerfile."
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`${ARTIFACTS_PATH} cannot be read. Do you need to run "make contracts-deploy-setup"?`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
|
||||||
|
/* Set up cosmos client & wallet */
|
||||||
|
|
||||||
|
let host = devnetConsts.chains[3104].tendermintUrlLocal
|
||||||
|
if (os.hostname().includes("wormchain-deploy")) {
|
||||||
|
// running in tilt devnet
|
||||||
|
host = devnetConsts.chains[3104].tendermintUrlTilt
|
||||||
|
}
|
||||||
|
const denom = devnetConsts.chains[3104].addresses.native.denom
|
||||||
|
const mnemonic = devnetConsts.chains[3104].accounts.wormchainNodeOfGuardian0.mnemonic
|
||||||
|
const addressPrefix = "wormhole"
|
||||||
|
|
||||||
|
const w = await Secp256k1HdWallet.fromMnemonic(mnemonic, { prefix: addressPrefix })
|
||||||
|
|
||||||
|
|
||||||
|
const gas = GasPrice.fromString(`0${denom}`)
|
||||||
|
let cwc: SigningCosmWasmClient
|
||||||
|
try {
|
||||||
|
cwc = await SigningCosmWasmClient.connectWithSigner(host, w, { prefix: addressPrefix, gasPrice: gas })
|
||||||
|
} catch (e) {
|
||||||
|
let msg = `could not connect to wormchain host: ${host}`
|
||||||
|
if (e?.message) {
|
||||||
|
console.error(e.message)
|
||||||
|
}
|
||||||
|
throw msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// there are several Cosmos chains in devnet, so check the config is as expected
|
||||||
|
let id = await cwc.getChainId()
|
||||||
|
if (id !== "wormchain") {
|
||||||
|
throw new Error(`Wormchain CosmWasmClient connection produced an unexpected chainID: ${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const signers = await w.getAccounts()
|
||||||
|
const signer = signers[0].address
|
||||||
|
console.log("wormchain contract deployer is: ", signer)
|
||||||
|
|
||||||
|
/* Deploy artifacts */
|
||||||
|
|
||||||
|
const codeIds: { [name: ContractName]: number } = await artifacts.reduce(async (prev, file) => {
|
||||||
|
// wait for the previous to finish, to avoid the race condition of wallet sequence mismatch.
|
||||||
|
const accum = await prev
|
||||||
|
|
||||||
|
const contract_bytes = await readFileAsync(`${ARTIFACTS_PATH}${file}`);
|
||||||
|
|
||||||
|
const i = await cwc.upload(signer, contract_bytes, "auto", "")
|
||||||
|
console.log(`uploaded ${file}, codeID: ${i.codeId}, tx: ${i.transactionHash}`, i.codeId, i.transactionHash)
|
||||||
|
|
||||||
|
accum[file] = i.codeId
|
||||||
|
return accum
|
||||||
|
}, Object())
|
||||||
|
|
||||||
|
// Instantiate contracts.
|
||||||
|
|
||||||
|
async function instantiate(code_id: number, inst_msg: any, label: string) {
|
||||||
|
let inst = await cwc.instantiate(signer, code_id, inst_msg, label, "auto", {})
|
||||||
|
let addr = inst.contractAddress
|
||||||
|
let txHash = inst.transactionHash
|
||||||
|
console.log(`deployed contract ${label}, codeID: ${code_id}, address: ${addr}, txHash: ${txHash}`)
|
||||||
|
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate contracts.
|
||||||
|
// NOTE: Only append at the end, the ordering must be deterministic.
|
||||||
|
|
||||||
|
const addresses: { [contractName: string]: InstantiateResult["transactionHash"] } = {};
|
||||||
|
|
||||||
|
const init_guardians: string[] = JSON.parse(String(process.env.INIT_SIGNERS));
|
||||||
|
if (!init_guardians || init_guardians.length === 0) {
|
||||||
|
throw "failed to get initial guardians from .env file.";
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses["mock.wasm"] = await instantiate(
|
||||||
|
codeIds["cw20_base.wasm"],
|
||||||
|
{
|
||||||
|
name: "MOCK",
|
||||||
|
symbol: "MCK",
|
||||||
|
decimals: 6,
|
||||||
|
initial_balances: [
|
||||||
|
{
|
||||||
|
address: signer,
|
||||||
|
amount: "100000000",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mint: null,
|
||||||
|
},
|
||||||
|
"mock"
|
||||||
|
);
|
||||||
|
console.log('instantiated cw20 MOCK token: ', addresses["mock.wasm"])
|
||||||
|
|
||||||
|
|
||||||
|
const registrations: { [chainName: string]: string } = {
|
||||||
|
// keys are only used for logging success/failure
|
||||||
|
"solana": String(process.env.REGISTER_SOL_TOKEN_BRIDGE_VAA),
|
||||||
|
"ethereum": String(process.env.REGISTER_ETH_TOKEN_BRIDGE_VAA),
|
||||||
|
"bsc": String(process.env.REGISTER_BSC_TOKEN_BRIDGE_VAA),
|
||||||
|
"algo": String(process.env.REGISTER_ALGO_TOKEN_BRIDGE_VAA),
|
||||||
|
"terra": String(process.env.REGISTER_TERRA_TOKEN_BRIDGE_VAA),
|
||||||
|
"near": String(process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA),
|
||||||
|
"terra2": String(process.env.REGISTER_TERRA2_TOKEN_BRIDGE_VAA),
|
||||||
|
"aptos": String(process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const instantiateMsg = {}
|
||||||
|
addresses["wormchain_accounting.wasm"] = await instantiate(
|
||||||
|
codeIds["wormchain_accounting.wasm"],
|
||||||
|
instantiateMsg,
|
||||||
|
"wormchainAccounting"
|
||||||
|
)
|
||||||
|
console.log("instantiated accounting: ", addresses["wormchain_accounting.wasm"])
|
||||||
|
|
||||||
|
const accountingRegistrations = Object.values(registrations)
|
||||||
|
.map(r => Buffer.from(r, "hex").toString("base64"))
|
||||||
|
|
||||||
|
const msg = {
|
||||||
|
typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract",
|
||||||
|
value: MsgExecuteContract.fromPartial({
|
||||||
|
sender: signer,
|
||||||
|
contract: addresses["wormchain_accounting.wasm"],
|
||||||
|
msg: toUtf8(JSON.stringify({
|
||||||
|
submit_v_a_as: {
|
||||||
|
vaas: accountingRegistrations,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const res = await cwc.signAndBroadcast(signer, [msg], "auto");
|
||||||
|
console.log(`sent accounting chain registrations, tx: `, res.transactionHash);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
main()
|
||||||
|
} catch (e: any) {
|
||||||
|
if (e?.message) {
|
||||||
|
console.error(e.message)
|
||||||
|
}
|
||||||
|
throw e
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "@wormhole-foundation/wormchain-contract-tools",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "scripts for working with wormchain contracts",
|
||||||
|
"main": "deploy_wormchain.ts",
|
||||||
|
"scripts": {
|
||||||
|
"deploy-wormchain": "ts-node deploy_wormchain.ts",
|
||||||
|
"test-wormchain": "ts-node test_wormchain.ts",
|
||||||
|
"deploy-and-test": "npm run deploy-wormchain && npm run test-wormchain"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@cosmjs/cosmwasm-stargate": "0.29.5",
|
||||||
|
"cosmwasm": "1.1.1",
|
||||||
|
"dotenv": "16.0.3",
|
||||||
|
"elliptic": "6.5.4",
|
||||||
|
"ethers": "5.7.2",
|
||||||
|
"web3-eth-abi": "1.8.1",
|
||||||
|
"yargs": "17.6.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/elliptic": "6.4.14",
|
||||||
|
"ts-node": "10.9.1",
|
||||||
|
"typescript": "4.9.4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
import "dotenv/config";
|
||||||
|
import * as os from "os"
|
||||||
|
import { SigningCosmWasmClient, toBinary } from "@cosmjs/cosmwasm-stargate";
|
||||||
|
import { GasPrice } from "@cosmjs/stargate"
|
||||||
|
import { fromBase64 } from "cosmwasm";
|
||||||
|
import { Secp256k1HdWallet } from "@cosmjs/amino";
|
||||||
|
|
||||||
|
import { zeroPad } from "ethers/lib/utils.js";
|
||||||
|
import { keccak256 } from "@cosmjs/crypto"
|
||||||
|
|
||||||
|
import * as elliptic from "elliptic"
|
||||||
|
import { concatArrays, encodeUint8 } from "./utils";
|
||||||
|
|
||||||
|
import * as devnetConsts from "./devnet-consts.json"
|
||||||
|
|
||||||
|
|
||||||
|
function signBinary(key: elliptic.ec.KeyPair, binary: string): Uint8Array {
|
||||||
|
// base64 string to Uint8Array,
|
||||||
|
// so we have bytes to work with for signing, though not sure 100% that's correct.
|
||||||
|
const bytes = fromBase64(binary);
|
||||||
|
|
||||||
|
// create the "digest" for signing.
|
||||||
|
// The contract will calculate the digest of the "data",
|
||||||
|
// then use that with the signature to ec recover the publickey that signed.
|
||||||
|
const digest = keccak256(keccak256(bytes));
|
||||||
|
|
||||||
|
// sign the digest
|
||||||
|
const signature = key.sign(digest, { canonical: true });
|
||||||
|
|
||||||
|
// create 65 byte signature (64 + 1)
|
||||||
|
const signedParts = [
|
||||||
|
zeroPad(signature.r.toBuffer(), 32),
|
||||||
|
zeroPad(signature.s.toBuffer(), 32),
|
||||||
|
encodeUint8(signature.recoveryParam || 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
// combine parts to be Uint8Array with length 65
|
||||||
|
const signed = concatArrays(signedParts);
|
||||||
|
|
||||||
|
return signed
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
|
||||||
|
/* Set up cosmos client & wallet */
|
||||||
|
|
||||||
|
const WORMCHAIN_ID = 3104
|
||||||
|
|
||||||
|
let host = devnetConsts.chains[3104].tendermintUrlLocal
|
||||||
|
if (os.hostname().includes("wormchain-deploy")) {
|
||||||
|
// running in tilt devnet
|
||||||
|
host = devnetConsts.chains[3104].tendermintUrlTilt
|
||||||
|
}
|
||||||
|
const denom = devnetConsts.chains[WORMCHAIN_ID].addresses.native.denom
|
||||||
|
const mnemonic = devnetConsts.chains[WORMCHAIN_ID].accounts.wormchainNodeOfGuardian0.mnemonic
|
||||||
|
const addressPrefix = "wormhole"
|
||||||
|
const signerPk = devnetConsts.devnetGuardians[0].private
|
||||||
|
const accountingAddress = devnetConsts.chains[WORMCHAIN_ID].contracts.accountingNativeAddress
|
||||||
|
|
||||||
|
const w = await Secp256k1HdWallet.fromMnemonic(mnemonic, { prefix: addressPrefix })
|
||||||
|
|
||||||
|
const gas = GasPrice.fromString(`0${denom}`)
|
||||||
|
let cwc = await SigningCosmWasmClient.connectWithSigner(host, w, { prefix: addressPrefix, gasPrice: gas })
|
||||||
|
|
||||||
|
// there is no danger here, just several Cosmos chains in devnet, so check for config issues
|
||||||
|
let id = await cwc.getChainId()
|
||||||
|
if (id !== "wormchain") {
|
||||||
|
throw new Error(`Wormchain CosmWasmClient connection produced an unexpected chainID: ${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const signers = await w.getAccounts()
|
||||||
|
const signer = signers[0].address
|
||||||
|
console.log("wormchain wallet pubkey: ", signer)
|
||||||
|
|
||||||
|
const nativeBalance = await cwc.getBalance(signer, denom)
|
||||||
|
console.log("nativeBalance ", nativeBalance.amount)
|
||||||
|
|
||||||
|
const utestBalance = await cwc.getBalance(signer, "utest")
|
||||||
|
console.log("utest balance ", utestBalance.amount)
|
||||||
|
|
||||||
|
|
||||||
|
// create key for guardian0
|
||||||
|
const ec = new elliptic.ec("secp256k1");
|
||||||
|
// create key from the devnet guardian0's private key
|
||||||
|
const key = ec.keyFromPrivate(Buffer.from(signerPk, "hex"));
|
||||||
|
|
||||||
|
|
||||||
|
// Test empty observation
|
||||||
|
|
||||||
|
// object to json string, then to base64 (serde binary)
|
||||||
|
const arrayBinaryString = toBinary([]);
|
||||||
|
|
||||||
|
// combine parts to be Uint8Array with length 65
|
||||||
|
const signedEmptyArray = signBinary(key, arrayBinaryString)
|
||||||
|
|
||||||
|
const observeEmptyArray = {
|
||||||
|
submit_observations: {
|
||||||
|
observations: arrayBinaryString,
|
||||||
|
guardian_set_index: 0,
|
||||||
|
signature: {
|
||||||
|
index: 0,
|
||||||
|
signature: Array.from(signedEmptyArray),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let emptyArrayObsRes = await cwc.execute(signer, accountingAddress, observeEmptyArray, "auto");
|
||||||
|
console.log(`emptyArrayObsRes.transactionHash: ${emptyArrayObsRes.transactionHash}`);
|
||||||
|
|
||||||
|
|
||||||
|
// Test (fake) observation
|
||||||
|
const emitter_address = "0000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16"
|
||||||
|
const observations = [
|
||||||
|
{
|
||||||
|
emitter_chain: 2,
|
||||||
|
emitter_address: emitter_address,
|
||||||
|
sequence: 2,
|
||||||
|
nonce: 1,
|
||||||
|
consistency_level: 0,
|
||||||
|
timestamp: 1,
|
||||||
|
payload:
|
||||||
|
Buffer.from("030000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000002d8be6bf0baa74e0a907016679cae9190e80dd0a0002000000000000000000000000c10820983f33456ce7beb3a046f5a83fa34f027d0c2000000000000000000000000000000000000000000000000000000000000f4240", "hex").toString("base64"),
|
||||||
|
|
||||||
|
tx_hash:
|
||||||
|
Buffer.from("9fc68fb0ee735d45c9074a20adef1747b0593803f33b9f3f2252c8e2df567f41", "hex").toString("base64")
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// object to json string, then to base64 (serde binary)
|
||||||
|
const observationsBinaryString = toBinary(observations);
|
||||||
|
|
||||||
|
const signed = signBinary(key, observationsBinaryString)
|
||||||
|
|
||||||
|
const executeMsg = {
|
||||||
|
submit_observations: {
|
||||||
|
observations: observationsBinaryString,
|
||||||
|
guardian_set_index: 0,
|
||||||
|
signature: {
|
||||||
|
index: 0,
|
||||||
|
signature: Array.from(signed),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
console.log(executeMsg);
|
||||||
|
|
||||||
|
let inst = await cwc.execute(
|
||||||
|
signer,
|
||||||
|
accountingAddress,
|
||||||
|
executeMsg,
|
||||||
|
"auto"
|
||||||
|
);
|
||||||
|
let txHash = inst.transactionHash;
|
||||||
|
console.log(`executed submit_observation! txHash: ${txHash}`);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
console.log("done, exiting success.")
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
main()
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
throw e
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"resolveJsonModule": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
export function concatArrays(arrays: Uint8Array[]): Uint8Array {
|
||||||
|
const totalLength = arrays.reduce((accum, x) => accum + x.length, 0);
|
||||||
|
const result = new Uint8Array(totalLength);
|
||||||
|
|
||||||
|
for (let i = 0, offset = 0; i < arrays.length; i++) {
|
||||||
|
result.set(arrays[i], offset);
|
||||||
|
offset += arrays[i].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
export function encodeUint8(value: number): Uint8Array {
|
||||||
|
if (value >= 2 ** 8 || value < 0) {
|
||||||
|
throw new Error(`Out of bound value in Uint8: ${value}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Uint8Array([value]);
|
||||||
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
{
|
{
|
||||||
"type": "cosmos",
|
"type": "cosmos",
|
||||||
"value": {
|
"value": {
|
||||||
"key": "default",
|
"key": "default",
|
||||||
"chain-id": "wormchain",
|
"chain-id": "wormchain",
|
||||||
"rpc-addr": "http://guardian-validator:26657",
|
"rpc-addr": "http://wormchain:26657",
|
||||||
"account-prefix": "wormhole",
|
"account-prefix": "wormhole",
|
||||||
"keyring-backend": "test",
|
"keyring-backend": "test",
|
||||||
"gas-adjustment": 1.2,
|
"gas-adjustment": 1.2,
|
||||||
"gas-prices": "0.01utest",
|
"gas-prices": "0.01utest",
|
||||||
"debug": true,
|
"debug": true,
|
||||||
"timeout": "20s",
|
"timeout": "20s",
|
||||||
"output-format": "json",
|
"output-format": "json",
|
||||||
"sign-mode": "direct"
|
"sign-mode": "direct"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue