diff --git a/clients/js/evm.ts b/clients/js/evm.ts index c88b82629..5903f7032 100644 --- a/clients/js/evm.ts +++ b/clients/js/evm.ts @@ -244,7 +244,7 @@ export async function execute_governance_evm( console.log("Hash: " + (await tb.registerChain(vaa, overrides)).hash) break default: - impossible(payload) + throw Error(`VAA is of type ${payload.type}, which is not a governance action`) } break diff --git a/clients/js/solana.ts b/clients/js/solana.ts index 5828061b4..0012bae35 100644 --- a/clients/js/solana.ts +++ b/clients/js/solana.ts @@ -63,7 +63,7 @@ export async function execute_governance_solana( ix = token_bridge.register_chain_ix(token_bridge_id.toString(), bridge_id.toString(), from.publicKey.toString(), vaa) break default: - ix = impossible(v.payload) + throw Error(`VAA is of type ${v.payload.type}, which is not a governance action`) } break diff --git a/clients/js/terra.ts b/clients/js/terra.ts index 3a7b74ccb..36987b530 100644 --- a/clients/js/terra.ts +++ b/clients/js/terra.ts @@ -91,8 +91,7 @@ export async function execute_governance_terra( console.log("Registering chain"); break; default: - impossible(payload); - execute_msg = impossible(payload); + throw Error(`VAA is of type ${payload.type}, which is not a governance action`) } break; default: diff --git a/clients/js/vaa.ts b/clients/js/vaa.ts index 2db344f8c..560a90a53 100644 --- a/clients/js/vaa.ts +++ b/clients/js/vaa.ts @@ -60,6 +60,7 @@ export type Payload = | PortalContractUpgrade<"NFTBridge"> | PortalRegisterChain<"TokenBridge"> | PortalRegisterChain<"NFTBridge"> + | TokenBridgeTransfer // TODO: add other types of payloads export function parse(buffer: Buffer): VAA { @@ -70,6 +71,7 @@ export function parse(buffer: Buffer): VAA { .or(portalContractUpgradeParser("NFTBridge")) .or(portalRegisterChainParser("TokenBridge")) .or(portalRegisterChainParser("NFTBridge")) + .or(tokenBridgeTransferParser()) const payload = parser.parse(vaa.payload) var myVAA = { ...vaa, payload } @@ -164,9 +166,24 @@ function vaaBody(vaa: VAA) { case "ContractUpgrade": payload_str = serialiseCoreContractUpgrade(payload) break + default: + impossible(payload) + break } break case "NFTBridge": + switch (payload.type) { + case "ContractUpgrade": + payload_str = serialisePortalContractUpgrade(payload) + break + case "RegisterChain": + payload_str = serialisePortalRegisterChain(payload) + break + default: + impossible(payload) + break + } + break case "TokenBridge": switch (payload.type) { case "ContractUpgrade": @@ -175,8 +192,17 @@ function vaaBody(vaa: VAA) { case "RegisterChain": payload_str = serialisePortalRegisterChain(payload) break + case "Transfer": + payload_str = serialiseTokenBridgeTransfer(payload) + break + default: + impossible(payload) + break } break + default: + impossible(payload) + break } const body = [ encode("uint32", vaa.timestamp), @@ -406,6 +432,76 @@ function serialisePortalRegisterChain { + return new P(new Parser() + .endianess("big") + .string("module", { + length: (_) => 0, + formatter: (_) => "TokenBridge" + }) + .uint8("type", { + assert: 1, + formatter: (_action) => "Transfer" + }) + .array("amount", { + type: "uint8", + lengthInBytes: 32, + formatter: (bytes) => BigNumber.from(bytes).toBigInt() + }) + .array("tokenAddress", { + type: "uint8", + lengthInBytes: 32, + formatter: (arr) => "0x" + Buffer.from(arr).toString("hex") + }) + .uint16("tokenChain") + .array("toAddress", { + type: "uint8", + lengthInBytes: 32, + formatter: (arr) => "0x" + Buffer.from(arr).toString("hex") + }) + .uint16("chain") + .array("fee", { + type: "uint8", + lengthInBytes: 32, + formatter: (bytes) => BigNumber.from(bytes).toBigInt() + }) + .string("end", { + greedy: true, + assert: str => str === "" + }) + ) +} + +function serialiseTokenBridgeTransfer(payload: TokenBridgeTransfer): string { + const body = [ + encode("uint8", 1), + encode("uint256", payload.amount), + encode("bytes32", hex(payload.tokenAddress)), + encode("uint16", payload.tokenChain), + encode("bytes32", hex(payload.toAddress)), + encode("uint16", payload.chain), + encode("uint256", payload.fee), + ] + return body.join("") +} + +//////////////////////////////////////////////////////////////////////////////// +// NFT bridge + // This function should be called after pattern matching on all possible options // of an enum (union) type, so that typescript can derive that no other options // are possible. If (from JavaScript land) an unsupported argument is passed