diff --git a/clients/js/aptos.ts b/clients/js/aptos.ts index 90b40dce5..3f6a10514 100644 --- a/clients/js/aptos.ts +++ b/clients/js/aptos.ts @@ -60,7 +60,7 @@ export async function execute_aptos( console.log("Registering chain") await callEntryFunc(network, rpc, `${contract}::register_chain`, "submit_vaa_entry", [], [bcsVAA]); break - case "AttestMeta": + case "AttestMeta": { console.log("Creating wrapped token") // Deploying a wrapped asset requires two transactions: // 1. Publish a new module under a resource account that defines a type T @@ -77,21 +77,29 @@ export async function execute_aptos( // resource account, which is seeded by the token bridge's address and // the origin information of the token. We can recompute this address // offline: - let tokenAddress = payload.tokenAddress; - let tokenChain = payload.tokenChain; + const tokenAddress = payload.tokenAddress; + const tokenChain = payload.tokenChain; assertChain(tokenChain); let wrappedContract = deriveWrappedAssetAddress(hex(contract), tokenChain, hex(tokenAddress)); // Tx 2. console.log(`Deploying resource account ${wrappedContract}`); - const token = new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString(`${wrappedContract}::coin::T`)); + let token = new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString(`${wrappedContract}::coin::T`)); await callEntryFunc(network, rpc, `${contract}::wrapped`, "create_wrapped_coin", [token], [bcsVAA]); break - case "Transfer": + } + case "Transfer": { console.log("Completing transfer") - await callEntryFunc(network, rpc, `${contract}::complete_transfer`, "submit_vaa_entry", [], [bcsVAA]); + // TODO: only handles wrapped assets for now + const tokenAddress = payload.tokenAddress; + const tokenChain = payload.tokenChain; + assertChain(tokenChain); + let wrappedContract = deriveWrappedAssetAddress(hex(contract), tokenChain, hex(tokenAddress)); + const token = new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString(`${wrappedContract}::coin::T`)); + await callEntryFunc(network, rpc, `${contract}::complete_transfer`, "submit_vaa_and_register_entry", [token], [bcsVAA]); break + } case "TransferWithPayload": throw Error("Can't complete payload 3 transfer from CLI") default: @@ -113,9 +121,12 @@ export function deriveWrappedAssetAddress( let chain: Buffer = Buffer.alloc(2); chain.writeUInt16BE(origin_chain); if (origin_address.length != 32) { - throw new Error(`${origin_address} is not 32 bytes long.`) + throw new Error(`${origin_address}`) } - return sha3_256(Buffer.concat([token_bridge_address, chain, Buffer.from("::", "ascii"), origin_address])); + // from https://github.com/aptos-labs/aptos-core/blob/25696fd266498d81d346fe86e01c330705a71465/aptos-move/framework/aptos-framework/sources/account.move#L90-L95 + let DERIVE_RESOURCE_ACCOUNT_SCHEME = Buffer.alloc(1); + DERIVE_RESOURCE_ACCOUNT_SCHEME.writeUInt8(255); + return sha3_256(Buffer.concat([token_bridge_address, chain, Buffer.from("::", "ascii"), origin_address, DERIVE_RESOURCE_ACCOUNT_SCHEME])); } export function deriveResourceAccount( @@ -143,7 +154,7 @@ export async function callEntryFunc( const accountFrom = new AptosAccount(new Uint8Array(Buffer.from(key, "hex"))); let client: AptosClient; // if rpc arg is passed in, then override default rpc value for that network - if (typeof rpc != 'undefined'){ + if (typeof rpc != 'undefined') { client = new AptosClient(rpc); } else { client = new AptosClient(NETWORKS[network]["aptos"].rpc); diff --git a/clients/js/cmds/aptos.ts b/clients/js/cmds/aptos.ts index 659e92d02..4b4b96401 100644 --- a/clients/js/cmds/aptos.ts +++ b/clients/js/cmds/aptos.ts @@ -218,6 +218,23 @@ exports.builder = function(y: typeof yargs) { }, async (argv) => { console.log(deriveResourceAccount(Buffer.from(hex(argv['account']).substring(2), 'hex'), argv['seed'])) }) + .command("derive-wrapped-address ", "Derive wrapped coin type", (yargs) => { + return yargs + .positional("chain", { + type: "string" + }) + .positional("origin-address", { + type: "string" + }) + .option("network", network_options) + }, async (argv) => { + // TODO(csongor): this should be pulled in from the sdk. + let token_bridge_address = Buffer.from("576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f", "hex"); + assertChain(argv["chain"]); + let chain = coalesceChainId(argv["chain"]); + let origin_address = Buffer.from(evm_address(argv["origin-address"]), "hex"); + console.log(deriveWrappedAssetAddress(token_bridge_address, chain, origin_address)) + }) .command("hash-contracts ", "Hash contract bytecodes for upgrade", (yargs) => { return yargs .positional("seed", { diff --git a/clients/js/main.ts b/clients/js/main.ts index b41d4e510..864d00d07 100644 --- a/clients/js/main.ts +++ b/clients/js/main.ts @@ -79,14 +79,14 @@ const GOVERNANCE_EMITTER = const OVERRIDES = { MAINNET: { aptos: { - token_bridge: "0x7041d0a5ae46a24fd5f1df67c54bf1a2e0fe7668ae9402e30e58f3ad452f9d52", - core: "0x799c8d35a610b6fa8ed33432e31c686c97b4ce4205fce88c13577615372e99a3" + token_bridge: "0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f", + core: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625" } }, TESTNET: { aptos: { - token_bridge: "0x7041d0a5ae46a24fd5f1df67c54bf1a2e0fe7668ae9402e30e58f3ad452f9d52", - core: "0x799c8d35a610b6fa8ed33432e31c686c97b4ce4205fce88c13577615372e99a3" + token_bridge: "0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f", + core: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625" } }, DEVNET: { @@ -97,7 +97,7 @@ const OVERRIDES = { } } -const CONTRACTS = { +export const CONTRACTS = { MAINNET: { ...SDK_CONTRACTS.MAINNET, ...OVERRIDES.MAINNET }, TESTNET: { ...SDK_CONTRACTS.TESTNET, ...OVERRIDES.TESTNET }, DEVNET: { ...SDK_CONTRACTS.DEVNET, ...OVERRIDES.DEVNET },