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
|
chmod +x build/main.js
|
||||||
npm link
|
npm link
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: build
|
||||||
|
./run_parse_tests
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build node_modules
|
rm -rf build node_modules
|
||||||
|
|
|
@ -221,6 +221,10 @@ export async function execute_evm(
|
||||||
console.log("Registering chain")
|
console.log("Registering chain")
|
||||||
console.log("Hash: " + (await nb.registerChain(vaa, overrides)).hash)
|
console.log("Hash: " + (await nb.registerChain(vaa, overrides)).hash)
|
||||||
break
|
break
|
||||||
|
case "Transfer":
|
||||||
|
console.log("Completing transfer")
|
||||||
|
console.log("Hash: " + (await nb.completeTransfer(vaa, overrides)).hash)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
impossible(payload)
|
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"
|
expected="$test_name.expected"
|
||||||
|
|
||||||
result=$(mktemp)
|
result=$(mktemp)
|
||||||
worm parse $(cat "$test") > "$result" 2>&1
|
node build/main.js parse $(cat "$test") > "$result" 2>&1
|
||||||
if [ $accept = true ]; then
|
if [ $accept = true ]; then
|
||||||
echo "Updating $test_name"
|
echo "Updating $test_name"
|
||||||
cat "$result" > "$expected"
|
cat "$result" > "$expected"
|
||||||
|
|
|
@ -46,9 +46,11 @@ export async function execute_solana(
|
||||||
console.log("Registering chain")
|
console.log("Registering chain")
|
||||||
ix = nft_bridge.register_chain_ix(nft_bridge_id.toString(), bridge_id.toString(), from.publicKey.toString(), vaa);
|
ix = nft_bridge.register_chain_ix(nft_bridge_id.toString(), bridge_id.toString(), from.publicKey.toString(), vaa);
|
||||||
break
|
break
|
||||||
|
case "Transfer":
|
||||||
|
throw Error("Can't redeem NFTs from CLI")
|
||||||
|
// TODO: what's the authority account? just bail for now
|
||||||
default:
|
default:
|
||||||
ix = impossible(v.payload)
|
ix = impossible(v.payload)
|
||||||
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "TokenBridge":
|
case "TokenBridge":
|
||||||
|
|
|
@ -72,6 +72,9 @@ export async function execute_terra(
|
||||||
case "RegisterChain":
|
case "RegisterChain":
|
||||||
console.log("Registering chain");
|
console.log("Registering chain");
|
||||||
break;
|
break;
|
||||||
|
case "Transfer":
|
||||||
|
console.log("Completing transfer");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
impossible(payload);
|
impossible(payload);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ export type Payload =
|
||||||
| TokenBridgeTransfer
|
| TokenBridgeTransfer
|
||||||
| TokenBridgeTransferWithPayload
|
| TokenBridgeTransferWithPayload
|
||||||
| TokenBridgeAttestMeta
|
| TokenBridgeAttestMeta
|
||||||
// TODO: add other types of payloads
|
| NFTBridgeTransfer
|
||||||
|
|
||||||
export type ContractUpgrade =
|
export type ContractUpgrade =
|
||||||
CoreContractUpgrade
|
CoreContractUpgrade
|
||||||
|
@ -81,7 +81,9 @@ export function parse(buffer: Buffer): VAA<Payload | null> {
|
||||||
.or(tokenBridgeTransferParser())
|
.or(tokenBridgeTransferParser())
|
||||||
.or(tokenBridgeTransferWithPayloadParser())
|
.or(tokenBridgeTransferWithPayloadParser())
|
||||||
.or(tokenBridgeAttestMetaParser())
|
.or(tokenBridgeAttestMetaParser())
|
||||||
|
.or(nftBridgeTransferParser())
|
||||||
const payload = parser.parse(vaa.payload)
|
const payload = parser.parse(vaa.payload)
|
||||||
|
delete payload['tokenURILength']
|
||||||
var myVAA = { ...vaa, payload }
|
var myVAA = { ...vaa, payload }
|
||||||
|
|
||||||
return myVAA
|
return myVAA
|
||||||
|
@ -188,6 +190,9 @@ function vaaBody(vaa: VAA<Payload>) {
|
||||||
case "RegisterChain":
|
case "RegisterChain":
|
||||||
payload_str = serialisePortalRegisterChain(payload)
|
payload_str = serialisePortalRegisterChain(payload)
|
||||||
break
|
break
|
||||||
|
case "Transfer":
|
||||||
|
payload_str = serialiseNFTBridgeTransfer(payload)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
impossible(payload)
|
impossible(payload)
|
||||||
break
|
break
|
||||||
|
@ -650,6 +655,88 @@ function serialiseTokenBridgeTransferWithPayload(payload: TokenBridgeTransferWit
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// NFT bridge
|
// 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
|
// 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
|
// 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
|
// are possible. If (from JavaScript land) an unsupported argument is passed
|
||||||
|
|
Loading…
Reference in New Issue