clients/js: Add support for NFT bridge transfers
commit-id:6b11415c
This commit is contained in:
parent
465916c3f8
commit
fa3cec16f6
|
@ -23,5 +23,9 @@ install: build
|
|||
chmod +x build/main.js
|
||||
npm link
|
||||
|
||||
.PHONY: test
|
||||
test: build
|
||||
./run_parse_tests
|
||||
|
||||
clean:
|
||||
rm -rf build node_modules
|
||||
|
|
|
@ -221,6 +221,10 @@ export async function execute_evm(
|
|||
console.log("Registering chain")
|
||||
console.log("Hash: " + (await nb.registerChain(vaa, overrides)).hash)
|
||||
break
|
||||
case "Transfer":
|
||||
console.log("Completing transfer")
|
||||
console.log("Hash: " + (await nb.completeTransfer(vaa, overrides)).hash)
|
||||
break
|
||||
default:
|
||||
impossible(payload)
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
version: 1,
|
||||
guardianSetIndex: 0,
|
||||
signatures: [],
|
||||
timestamp: 1,
|
||||
nonce: 1,
|
||||
emitterChain: 1,
|
||||
emitterAddress: '0x0000000000000000000000000000000000000000000000000000000000000004',
|
||||
sequence: 41401099n,
|
||||
consistencyLevel: 0,
|
||||
payload: {
|
||||
module: 'NFTBridge',
|
||||
type: 'Transfer',
|
||||
tokenAddress: '0x0000000000000000000000000000000000000000000000000000000000000004',
|
||||
tokenChain: 1,
|
||||
tokenSymbol: 'FOO',
|
||||
tokenName: 'BAR',
|
||||
tokenId: 10n,
|
||||
tokenURI: 'google.com',
|
||||
toAddress: '0x0000000000000000000000000000000000000000000000000000000000000004',
|
||||
chain: 10
|
||||
},
|
||||
digest: '0xe2a7a0f5d67018c74683851fca870403455f89d9f474e2af104740e31a00da63'
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
010000000000000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000277bb0b0001000000000000000000000000000000000000000000000000000000000000000400010000000000000000000000000000000000000000000000000000000000464f4f0000000000000000000000000000000000000000000000000000000000424152000000000000000000000000000000000000000000000000000000000000000a0a676f6f676c652e636f6d0000000000000000000000000000000000000000000000000000000000000004000a
|
|
@ -42,7 +42,7 @@ for test in ${test_files[@]}; do
|
|||
expected="$test_name.expected"
|
||||
|
||||
result=$(mktemp)
|
||||
worm parse $(cat "$test") > "$result" 2>&1
|
||||
node build/main.js parse $(cat "$test") > "$result" 2>&1
|
||||
if [ $accept = true ]; then
|
||||
echo "Updating $test_name"
|
||||
cat "$result" > "$expected"
|
||||
|
|
|
@ -46,9 +46,11 @@ export async function execute_solana(
|
|||
console.log("Registering chain")
|
||||
ix = nft_bridge.register_chain_ix(nft_bridge_id.toString(), bridge_id.toString(), from.publicKey.toString(), vaa);
|
||||
break
|
||||
case "Transfer":
|
||||
throw Error("Can't redeem NFTs from CLI")
|
||||
// TODO: what's the authority account? just bail for now
|
||||
default:
|
||||
ix = impossible(v.payload)
|
||||
|
||||
}
|
||||
break
|
||||
case "TokenBridge":
|
||||
|
|
|
@ -72,6 +72,9 @@ export async function execute_terra(
|
|||
case "RegisterChain":
|
||||
console.log("Registering chain");
|
||||
break;
|
||||
case "Transfer":
|
||||
console.log("Completing transfer");
|
||||
break;
|
||||
default:
|
||||
impossible(payload);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ export type Payload =
|
|||
| TokenBridgeTransfer
|
||||
| TokenBridgeTransferWithPayload
|
||||
| TokenBridgeAttestMeta
|
||||
// TODO: add other types of payloads
|
||||
| NFTBridgeTransfer
|
||||
|
||||
export type ContractUpgrade =
|
||||
CoreContractUpgrade
|
||||
|
@ -81,7 +81,9 @@ export function parse(buffer: Buffer): VAA<Payload | null> {
|
|||
.or(tokenBridgeTransferParser())
|
||||
.or(tokenBridgeTransferWithPayloadParser())
|
||||
.or(tokenBridgeAttestMetaParser())
|
||||
.or(nftBridgeTransferParser())
|
||||
const payload = parser.parse(vaa.payload)
|
||||
delete payload['tokenURILength']
|
||||
var myVAA = { ...vaa, payload }
|
||||
|
||||
return myVAA
|
||||
|
@ -188,6 +190,9 @@ function vaaBody(vaa: VAA<Payload>) {
|
|||
case "RegisterChain":
|
||||
payload_str = serialisePortalRegisterChain(payload)
|
||||
break
|
||||
case "Transfer":
|
||||
payload_str = serialiseNFTBridgeTransfer(payload)
|
||||
break
|
||||
default:
|
||||
impossible(payload)
|
||||
break
|
||||
|
@ -650,6 +655,88 @@ function serialiseTokenBridgeTransferWithPayload(payload: TokenBridgeTransferWit
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NFT bridge
|
||||
|
||||
export interface NFTBridgeTransfer {
|
||||
module: "NFTBridge"
|
||||
type: "Transfer"
|
||||
tokenAddress: string
|
||||
tokenChain: number
|
||||
tokenSymbol: string
|
||||
tokenName: string
|
||||
tokenId: bigint
|
||||
tokenURI: string
|
||||
toAddress: string
|
||||
chain: number
|
||||
}
|
||||
|
||||
function nftBridgeTransferParser(): P<NFTBridgeTransfer> {
|
||||
return new P(new Parser()
|
||||
.endianess("big")
|
||||
.string("module", {
|
||||
length: (_) => 0,
|
||||
formatter: (_) => "NFTBridge"
|
||||
})
|
||||
.uint8("type", {
|
||||
assert: 1,
|
||||
formatter: (_action) => "Transfer"
|
||||
})
|
||||
.array("tokenAddress", {
|
||||
type: "uint8",
|
||||
lengthInBytes: 32,
|
||||
formatter: (arr) => "0x" + Buffer.from(arr).toString("hex")
|
||||
})
|
||||
.uint16("tokenChain")
|
||||
.array("tokenSymbol", {
|
||||
type: "uint8",
|
||||
lengthInBytes: 32,
|
||||
formatter: (arr: Uint8Array) => Buffer.from(arr).toString("utf8", arr.findIndex((val) => val != 0))
|
||||
})
|
||||
.array("tokenName", {
|
||||
type: "uint8",
|
||||
lengthInBytes: 32,
|
||||
formatter: (arr: Uint8Array) => Buffer.from(arr).toString("utf8", arr.findIndex((val) => val != 0))
|
||||
})
|
||||
.array("tokenId", {
|
||||
type: "uint8",
|
||||
lengthInBytes: 32,
|
||||
formatter: (bytes) => BigNumber.from(bytes).toBigInt()
|
||||
})
|
||||
.uint8("tokenURILength")
|
||||
.array("tokenURI", {
|
||||
type: "uint8",
|
||||
lengthInBytes: function() {
|
||||
return this.tokenURILength
|
||||
},
|
||||
formatter: (arr: Uint8Array) => Buffer.from(arr).toString("utf8")
|
||||
})
|
||||
.array("toAddress", {
|
||||
type: "uint8",
|
||||
lengthInBytes: 32,
|
||||
formatter: (arr) => "0x" + Buffer.from(arr).toString("hex")
|
||||
})
|
||||
.uint16("chain")
|
||||
.string("end", {
|
||||
greedy: true,
|
||||
assert: str => str === ""
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
function serialiseNFTBridgeTransfer(payload: NFTBridgeTransfer): string {
|
||||
const body = [
|
||||
encode("uint8", 1),
|
||||
encode("bytes32", hex(payload.tokenAddress)),
|
||||
encode("uint16", payload.tokenChain),
|
||||
encode("bytes32", encodeString(payload.tokenSymbol)),
|
||||
encode("bytes32", encodeString(payload.tokenName)),
|
||||
encode("uint256", payload.tokenId),
|
||||
encode("uint8", payload.tokenURI.length),
|
||||
Buffer.from(payload.tokenURI, "utf8").toString("hex"),
|
||||
encode("bytes32", hex(payload.toAddress)),
|
||||
encode("uint16", payload.chain),
|
||||
]
|
||||
return body.join("")
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
Loading…
Reference in New Issue