2.1 Direct Interaction with On-chain Contracts

2.1.1 EVM Compatible Chains

There are two contract interfaces available: userLock and userBurn.

  • For tokens whose names include @ (e.g., wanUSDT@wanchainWAN@ethereum), which are WanBridge Wrapped Tokens, the userBurn interface needs to be called.

  • For all other tokens, the userLock interface should be used.

  • For all ERC-20 tokens, an approve transaction must be executed first.

function userLock(bytes32 smgID, uint tokenPairID, uint value, bytes userAccount)
    external
    payable

function userBurn(bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, bytes userAccount)
    external
    payable

2.1.2 Tron

The process for Tron follows the same structure as described in 2.1.1 EVM-Compatible Chains.

2.1.3 Solana

There are two transaction types: userLock and userBurn. For tokens on Solana, users must determine whether they are Solana-native tokens or Wanchain-mapped tokens.

Determining Token Type and Transaction Type

  • If the token is a Wanchain-mapped token, use the userBurn transaction type.

  • If the token is a Solana-native token, use the userLock transaction type.

General Transaction Requirements

For cross-chain transactions, you can build transactions using your preferred wallet and Solana libraries such as solana-web3.js and anchor.

2.1.3.1 userLock Transaction Type

Program requirements

  • programId: E3iKvJgGNycXrmsh2aryY25z29PpU4dvo4CBuXCKQiGB

Instruction Definition

pub fn user_lock(ctx: Context<UserLock>, smg_id: [u8; 32], token_pair_id: u32, amount: u64, user_account: Vec<u8>)

Accounts Requirements

  • user: User wallet account

  • sol_vault: AKXdNCG4GcTQ1knC7kno9bggHuq8MG9CCb8yQd8Nx2vL

    • programId: E3iKvJgGNycXrmsh2aryY25z29PpU4dvo4CBuXCKQiGB

    • seeds: [Buffer.from("vault", "utf8")]

  • user_ata: Token ATA account for the user wallet; null if the cross-chain token is SOL

  • token_vault: Token ATA account for sol_vault; null if the cross-chain token is SOL

  • mapping_token_mint: Cross-chain token account; null if the cross-chain token is SOL

  • fee_receiver: CXxYYAtiUhdUagJNQ6UAB9gmHdxeujUPdn4iRg9HeuSz

  • admin_board_program: 7jYCM8k5Nvwg5vyPpLk2yjivQhexPDMXuK8CSbUKqL6B

  • config_account: 9o7zWu1n3q1MCAQp5y8RYmhhVjNpkfhpbSDMeYvjwhZP

  • token_pair_account: Token pair account for the token pair ID

    • programId: 7jYCM8k5Nvwg5vyPpLk2yjivQhexPDMXuK8CSbUKqL6B

    • seeds: [Buffer.from("TokenPairInfo", "utf8"), new BN(tokenPairId).toArrayLike(Buffer, "le", 4)]

  • cctp_admin_board_fee_account: Chain fee account for the target chain ID from token pair info

    • programId: dFYBRAFvZKq9F4mYGkLQu8DbfZRFrmi5dNSTDfwC3a8

    • seeds: [Buffer.from("FeeData", "utf8"), new BN(toChainId).toArrayLike(Buffer, "le", 4)]

  • token_program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA

  • associated_token_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL

  • system_program: 11111111111111111111111111111111

2.1.3.2 userBurn Transaction Type

Program Requirements

  • programId: E3iKvJgGNycXrmsh2aryY25z29PpU4dvo4CBuXCKQiGB

Instruction Definition

pub fn user_burn(ctx: Context<UserBurn>, smg_id: [u8; 32], token_pair_id: u32, amount: u64, fee: u64, token_account:  Pubkey, user_account: Vec<u8>)

Accounts Requirements

  • user: User wallet account

  • user_ata: Token ATA account for the user wallet

  • mapping_token_mint: Cross-chain token account

  • config_account: 9o7zWu1n3q1MCAQp5y8RYmhhVjNpkfhpbSDMeYvjwhZP

  • token_manager_program: 6PcqfvWkBv3m9F5XBU2kMAedycs6BPzDGfi8zcWam3kH

  • fee_receiver: CXxYYAtiUhdUagJNQ6UAB9gmHdxeujUPdn4iRg9HeuSz

  • admin_board_program: 7jYCM8k5Nvwg5vyPpLk2yjivQhexPDMXuK8CSbUKqL6B

  • token_pair_account: Token pair account for the token pair ID

    • programId: 7jYCM8k5Nvwg5vyPpLk2yjivQhexPDMXuK8CSbUKqL6B

    • seeds: [Buffer.from("TokenPairInfo", "utf8"), new BN(tokenPairId).toArrayLike(Buffer, "le", 4)]

  • cctp_admin_board_fee_account: Chain fee account for the target chain ID from token pair info

    • programId: dFYBRAFvZKq9F4mYGkLQu8DbfZRFrmi5dNSTDfwC3a8

    • seeds: [Buffer.from("FeeData", "utf8"), new BN(toChainId).toArrayLike(Buffer, "le", 4)]

  • token_program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA

  • associated_token_program: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL

  • system_program: 11111111111111111111111111111111

2.1.3.3 References

PublicKey.findProgramAddressSync

Solana Documentation

2.1.4 ADA

There are two types of transactions: userLock and userBurn. For tokens on the Cardano network, the user must determine whether they are Cardano native tokens or Wanchain-mapped tokens.

Determine Cardano Token Types and Transaction Types

  • If the token policy ID is 25c5de5f5b286073c593edfd77b48abc7a48e5a4f3d4cd9d428ff935, the token is a Wanchain-mapped token, and the userBurn transaction type should be used.

  • If the token policy ID is any other value, the token is a Cardano native token, and the userLock transaction type should be used.

General Transaction Requirements

For cross-chain transactions, users can build transactions using their preferred wallet along with the Lucid library or other libraries.

  • If a network fee is required, the transaction must include an additional output UTXO in ADA with the actual networkFee, sent to the fee receiver address: addr1qyxqtjnck8f0gyzys6kwpydd5lrcjue6tg8f2elqhs65ffy7trczz375trxwfgc7zvkvxrxcr4plz8tnqv6qre7u722qhe650r

2.1.4.1 userLock Transaction Type

Metadata Requirements for Cross-Chain Information

let data = {
  1: {
    type: TX_TYPE.userLock,
    tokenPairID: Number(tokenPairID),
    fromAccount: this.tool.splitMetadata(fromAccount),
    toAccount,
    smgID
  }
};

data = this.wasm.encode_json_str_to_metadatum(JSON.stringify(data), this.wasm.MetadataJsonSchema.BasicConversions);
return this.wasm.GeneralTransactionMetadata.from_bytes(data.to_bytes());

Metadata Example from Cardano Explorer

1
{
    "type": 1,
    "smgID": "0x000000000000000000000000000000000000000000000041726965735f303333",
    "toAccount": "0x8b157b3ffead48c8a4cdc6bddbe1c1d170049da4",
    "fromAccount": [
        "addr1q8nd57644dctpmh5z49u9kxdsr6t2px0jg0es4gjpy7kvzk2decd8n4d28t",
        "9helaqh6eq8tqpqxjn5km60dxreegmzuqesanym"
    ],
    "tokenPairID": 553
}

Output Requirements to Locked Account of Cardano Contract

  • Only one output UTXO to the locked address is allowed.

  • Inline Datum:

    let ls = wasm.PlutusList.new();
    ls.add(wasm.PlutusData.new_integer(wasm.BigInt.from_str('1')));
    return wasm.PlutusData.new_constr_plutus_data(
        wasm.ConstrPlutusData.new(
            wasm.BigNum.from_str('0'),
            ls
        )
    )
    

Inline Datum Example from Cardano Explorer

{
    "fields": [
        {
            "int": 1
        }
    ],
    "constructor": 0
}

2.1.4.2 userBurn Transaction Type

Metadata Requirements for Cross-Chain Information

let data = {
  1: {
    type: TX_TYPE.userBurn,
    tokenPairID: Number(tokenPairID),
    fromAccount: this.tool.splitMetadata(fromAccount),
    toAccount,
    smgID
  }
};
data = this.wasm.encode_json_str_to_metadatum(JSON.stringify(data), this.wasm.MetadataJsonSchema.BasicConversions);
return this.wasm.GeneralTransactionMetadata.from_bytes(data.to_bytes());

Metadata Example from Cardano Explorer

1
{
    "type": 8,
    "smgID": "0x000000000000000000000000000000000000000000000041726965735f303335",
    "toAccount": "0xca077dff2499ca3338d039abdc1939c287ca8690",
    "fromAccount": [
        "addr1qyrpkudmpvwyy79senufvfzc6dfq5qszkp6h099wrjcngp3zvct9scn6xme",
        "ks504tjgkmdd4wjjk9j6y3k6g9cthjlusuy3lpm"
    ],
    "tokenPairID": 510
}

Minting Requirements

  • The transaction must include only one token mint for the cross-chain token and amount.

2.1.4.3 References

Referene codes for Cardano transaction handling in cross-chain SDK:

Reference cross-chain transaction examples:

Last updated