sdk/js: Near refactor, added integration tests (#1648)
* near-sdk-refactor: Fix attest : Fix missing function calls : make near on near : renamed tryHexToNativeStringNear * near-sdk-refactor: bumped near-sdk-js version Co-authored-by: Josh Siegel <jsiegel@jumptrading.com>
This commit is contained in:
parent
02cf08531e
commit
c5d2f9d54d
6
Tiltfile
6
Tiltfile
|
@ -124,6 +124,7 @@ docker_build(
|
|||
context = ".",
|
||||
dockerfile = "Dockerfile.node",
|
||||
target = "build",
|
||||
ignore=["./sdk/js"]
|
||||
)
|
||||
|
||||
def command_with_dlv(argv):
|
||||
|
@ -697,9 +698,10 @@ if near:
|
|||
)
|
||||
|
||||
docker_build(
|
||||
ref = "near-contracts",
|
||||
ref = "near-deploy",
|
||||
context = "near",
|
||||
dockerfile = "near/Dockerfile.contracts",
|
||||
dockerfile = "near/Dockerfile.deploy",
|
||||
ignore = ["./test"]
|
||||
)
|
||||
|
||||
k8s_resource(
|
||||
|
|
|
@ -14,7 +14,7 @@ export async function execute_near(
|
|||
let contracts = CONTRACTS[network]["near"];
|
||||
|
||||
let target_contract = "";
|
||||
let numSubmits = 1
|
||||
let numSubmits = 1;
|
||||
|
||||
switch (payload.module) {
|
||||
case "Core":
|
||||
|
@ -37,7 +37,7 @@ export async function execute_near(
|
|||
if (contracts.nft_bridge === undefined) {
|
||||
throw new Error("NFT bridge not supported yet for near");
|
||||
}
|
||||
numSubmits = 2
|
||||
numSubmits = 2;
|
||||
target_contract = contracts.nft_bridge;
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
|
@ -57,7 +57,7 @@ export async function execute_near(
|
|||
if (contracts.token_bridge === undefined) {
|
||||
throw new Error("Token bridge not supported yet for near");
|
||||
}
|
||||
numSubmits = 2
|
||||
numSubmits = 2;
|
||||
target_contract = contracts.token_bridge;
|
||||
switch (payload.type) {
|
||||
case "ContractUpgrade":
|
||||
|
@ -89,9 +89,7 @@ export async function execute_near(
|
|||
keyStore.setKey(n.networkId, n.deployerAccount, key);
|
||||
|
||||
let near = await nearAPI.connect({
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: n.networkId,
|
||||
nodeUrl: n.rpc,
|
||||
});
|
||||
|
@ -111,7 +109,7 @@ export async function execute_near(
|
|||
|
||||
if (numSubmits <= 1) {
|
||||
console.log("Hash: " + result1.transaction.hash);
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// You have to feed a vaa twice into the contract (two submits),
|
||||
|
|
|
@ -216,6 +216,8 @@ const contract_registrations = {
|
|||
process.env.REGISTER_ALGO_TOKEN_BRIDGE_VAA,
|
||||
// TERRA
|
||||
process.env.REGISTER_TERRA_TOKEN_BRIDGE_VAA,
|
||||
// NEAR
|
||||
process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA,
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ spec:
|
|||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- "npm run migrate && npx truffle exec scripts/deploy_test_token.js && npm run deploy-batched-vaa-sender && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_bsc_chain.js && npx truffle exec scripts/register_algo_chain.js && nc -lkp 2000 0.0.0.0"
|
||||
- "npm run migrate && npx truffle exec scripts/deploy_test_token.js && npm run deploy-batched-vaa-sender && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_bsc_chain.js && npx truffle exec scripts/register_algo_chain.js && npx truffle exec scripts/register_near_chain.js && nc -lkp 2000 0.0.0.0"
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 300
|
||||
|
|
|
@ -55,7 +55,7 @@ spec:
|
|||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1/EVM_CHAIN_ID=1397/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_eth_chain.js && npx truffle exec scripts/register_algo_chain.js && nc -lkp 2000 0.0.0.0"
|
||||
- "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1/EVM_CHAIN_ID=1397/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_eth_chain.js && npx truffle exec scripts/register_algo_chain.js && npx truffle exec scripts/register_near_chain.js && nc -lkp 2000 0.0.0.0"
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 300
|
||||
|
|
|
@ -46,12 +46,12 @@ spec:
|
|||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3030
|
||||
- name: near-contracts
|
||||
image: near-contracts
|
||||
- name: near-deploy
|
||||
image: near-deploy
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- "sh devnet_deploy.sh && touch success && sleep infinity"
|
||||
- "sh /app/devnet_deploy.sh && touch success && sleep infinity"
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 3030
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// run this script with truffle exec
|
||||
|
||||
const jsonfile = require("jsonfile");
|
||||
const TokenBridge = artifacts.require("TokenBridge");
|
||||
const BridgeImplementationFullABI = jsonfile.readFileSync(
|
||||
"../build/contracts/BridgeImplementation.json"
|
||||
).abi;
|
||||
const nearTokenBridgeVAA = process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA;
|
||||
|
||||
module.exports = async function (callback) {
|
||||
try {
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
const tokenBridge = new web3.eth.Contract(
|
||||
BridgeImplementationFullABI,
|
||||
TokenBridge.address
|
||||
);
|
||||
|
||||
// Register the near token bridge endpoint
|
||||
await tokenBridge.methods.registerChain("0x" + nearTokenBridgeVAA).send({
|
||||
value: 0,
|
||||
from: accounts[0],
|
||||
gasLimit: 2000000,
|
||||
});
|
||||
|
||||
callback();
|
||||
} catch (e) {
|
||||
callback(e);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
FROM debian@sha256:2ce44bbc00a79113c296d9d25524e15d423b23303fdbbe20190d2f96e0aeb251 as build
|
||||
|
||||
RUN apt-get update && apt-get install -y curl \
|
||||
make \
|
||||
build-essential
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./setup-rust.sh .
|
||||
RUN ./setup-rust.sh
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN ./build-contracts.sh
|
||||
|
||||
FROM node:16-alpine@sha256:004dbac84fed48e20f9888a23e32fa7cf83c2995e174a78d41d9a9dd1e051a20 AS deploy
|
||||
|
||||
WORKDIR /app
|
||||
COPY package.json .
|
||||
COPY package-lock.json .
|
||||
COPY .env .
|
||||
COPY devnet_deploy.sh .
|
||||
COPY devnet_deploy.ts .
|
||||
COPY --from=build /app/contracts/*/target/wasm32-unknown-unknown/release/*.wasm .
|
||||
|
||||
# mount the buildkit cache on npm's cache dir, install dependencies
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci --production
|
||||
|
||||
|
|
@ -59,9 +59,7 @@ async function initNear() {
|
|||
keyStore.setKey(config.networkId, config.masterAccount, masterKey);
|
||||
|
||||
let near = await nearAPI.connect({
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: config.networkId,
|
||||
nodeUrl: config.nodeUrl,
|
||||
});
|
||||
|
@ -76,21 +74,25 @@ async function initNear() {
|
|||
);
|
||||
|
||||
if (e === "sandbox") {
|
||||
let da = parseSeedPhrase("weather opinion slam purpose access artefact word orbit matter rice poem badge");
|
||||
console.log(da);
|
||||
let resp = await masterAccount.createAccount(
|
||||
"devnet.test.near",
|
||||
da.publicKey,
|
||||
new BN(10).pow(new BN(27))
|
||||
);
|
||||
let da = parseSeedPhrase(
|
||||
"weather opinion slam purpose access artefact word orbit matter rice poem badge"
|
||||
);
|
||||
console.log(da);
|
||||
let resp = await masterAccount.createAccount(
|
||||
"devnet.test.near",
|
||||
da.publicKey,
|
||||
new BN(10).pow(new BN(27))
|
||||
);
|
||||
|
||||
console.log("devnet.test.near funded");
|
||||
console.log("devnet.test.near funded");
|
||||
}
|
||||
|
||||
const wormholeContract = await fs.readFileSync("./near_wormhole.wasm");
|
||||
const tokenContract = await fs.readFileSync("./near_token_bridge.wasm");
|
||||
const nftContract = await fs.readFileSync("./near_nft_bridge.wasm");
|
||||
const testContract = await fs.readFileSync("./near_mock_bridge_integration.wasm");
|
||||
const testContract = await fs.readFileSync(
|
||||
"./near_mock_bridge_integration.wasm"
|
||||
);
|
||||
|
||||
let wormholeAccount: any;
|
||||
|
||||
|
@ -108,27 +110,27 @@ async function initNear() {
|
|||
new BN("20000000000000000000000000")
|
||||
);
|
||||
|
||||
await wormholeAccount.functionCall({
|
||||
contractId: config.wormholeAccount,
|
||||
methodName: "register_emitter",
|
||||
args: {emitter: config.tokenAccount},
|
||||
attachedDeposit: new BN("30000000000000000000000"),
|
||||
gas: new BN("100000000000000"),
|
||||
})
|
||||
await wormholeAccount.functionCall({
|
||||
contractId: config.wormholeAccount,
|
||||
methodName: "register_emitter",
|
||||
args: {emitter: config.testAccount},
|
||||
attachedDeposit: new BN("30000000000000000000000"),
|
||||
gas: new BN("100000000000000"),
|
||||
})
|
||||
await wormholeAccount.functionCall({
|
||||
contractId: config.wormholeAccount,
|
||||
methodName: "register_emitter",
|
||||
args: {emitter: config.nftAccount},
|
||||
attachedDeposit: new BN("30000000000000000000000"),
|
||||
gas: new BN("100000000000000"),
|
||||
})
|
||||
await wormholeAccount.functionCall({
|
||||
contractId: config.wormholeAccount,
|
||||
methodName: "register_emitter",
|
||||
args: { emitter: config.tokenAccount },
|
||||
attachedDeposit: new BN("30000000000000000000000"),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
await wormholeAccount.functionCall({
|
||||
contractId: config.wormholeAccount,
|
||||
methodName: "register_emitter",
|
||||
args: { emitter: config.testAccount },
|
||||
attachedDeposit: new BN("30000000000000000000000"),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
await wormholeAccount.functionCall({
|
||||
contractId: config.wormholeAccount,
|
||||
methodName: "register_emitter",
|
||||
args: { emitter: config.nftAccount },
|
||||
attachedDeposit: new BN("30000000000000000000000"),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
} else {
|
||||
// This uses the standard API to redeploy ... we can migrate over to the vaa's later
|
||||
console.log(
|
||||
|
@ -140,18 +142,17 @@ async function initNear() {
|
|||
);
|
||||
await wormholeAccount.deployContract(wormholeContract);
|
||||
|
||||
// console.log("migrating " + config.wormholeAccount);
|
||||
// console.log(
|
||||
// await wormholeAccount.functionCall({
|
||||
// contractId: config.wormholeAccount,
|
||||
// methodName: "migrate",
|
||||
// args: {},
|
||||
// attachedDeposit: new BN(1),
|
||||
// gas: new BN("100000000000000"),
|
||||
// })
|
||||
// );
|
||||
// console.log("done migrating " + config.tokenAccount);
|
||||
|
||||
// console.log("migrating " + config.wormholeAccount);
|
||||
// console.log(
|
||||
// await wormholeAccount.functionCall({
|
||||
// contractId: config.wormholeAccount,
|
||||
// methodName: "migrate",
|
||||
// args: {},
|
||||
// attachedDeposit: new BN(1),
|
||||
// gas: new BN("100000000000000"),
|
||||
// })
|
||||
// );
|
||||
// console.log("done migrating " + config.tokenAccount);
|
||||
}
|
||||
|
||||
let tokenAccount: any;
|
||||
|
@ -170,19 +171,21 @@ async function initNear() {
|
|||
tokenAccount = new nearAPI.Account(near.connection, config.tokenAccount);
|
||||
await tokenAccount.deployContract(tokenContract);
|
||||
|
||||
console.log( await tokenAccount.viewFunction(config.tokenAccount, "emitter", {}));
|
||||
console.log(
|
||||
await tokenAccount.viewFunction(config.tokenAccount, "emitter", {})
|
||||
);
|
||||
|
||||
// console.log("migrating " + config.tokenAccount);
|
||||
// console.log(
|
||||
// await tokenAccount.functionCall({
|
||||
// contractId: config.tokenAccount,
|
||||
// methodName: "migrate",
|
||||
// args: {},
|
||||
// attachedDeposit: new BN(1),
|
||||
// gas: new BN("100000000000000"),
|
||||
// })
|
||||
// );
|
||||
// console.log("done migrating " + config.tokenAccount);
|
||||
// console.log("migrating " + config.tokenAccount);
|
||||
// console.log(
|
||||
// await tokenAccount.functionCall({
|
||||
// contractId: config.tokenAccount,
|
||||
// methodName: "migrate",
|
||||
// args: {},
|
||||
// attachedDeposit: new BN(1),
|
||||
// gas: new BN("100000000000000"),
|
||||
// })
|
||||
// );
|
||||
// console.log("done migrating " + config.tokenAccount);
|
||||
}
|
||||
|
||||
let nftAccount: any;
|
||||
|
@ -286,33 +289,33 @@ async function initNear() {
|
|||
});
|
||||
}
|
||||
|
||||
// for (const line of vaasNFT) {
|
||||
// console.log("Submitting to " + config.nftAccount + ": " + line);
|
||||
//
|
||||
// try {
|
||||
// await masterAccount.functionCall({
|
||||
// contractId: config.nftAccount,
|
||||
// methodName: "submit_vaa",
|
||||
// args: {
|
||||
// vaa: line,
|
||||
// },
|
||||
// attachedDeposit: new BN("30000000000000000000000"),
|
||||
// gas: new BN("300000000000000"),
|
||||
// });
|
||||
//
|
||||
// await masterAccount.functionCall({
|
||||
// contractId: config.nftAccount,
|
||||
// methodName: "submit_vaa",
|
||||
// args: {
|
||||
// vaa: line,
|
||||
// },
|
||||
// attachedDeposit: new BN("30000000000000000000000"),
|
||||
// gas: new BN("300000000000000"),
|
||||
// });
|
||||
// } catch {
|
||||
// console.log("Exception thrown.. ");
|
||||
// }
|
||||
// }
|
||||
// for (const line of vaasNFT) {
|
||||
// console.log("Submitting to " + config.nftAccount + ": " + line);
|
||||
//
|
||||
// try {
|
||||
// await masterAccount.functionCall({
|
||||
// contractId: config.nftAccount,
|
||||
// methodName: "submit_vaa",
|
||||
// args: {
|
||||
// vaa: line,
|
||||
// },
|
||||
// attachedDeposit: new BN("30000000000000000000000"),
|
||||
// gas: new BN("300000000000000"),
|
||||
// });
|
||||
//
|
||||
// await masterAccount.functionCall({
|
||||
// contractId: config.nftAccount,
|
||||
// methodName: "submit_vaa",
|
||||
// args: {
|
||||
// vaa: line,
|
||||
// },
|
||||
// attachedDeposit: new BN("30000000000000000000000"),
|
||||
// gas: new BN("300000000000000"),
|
||||
// });
|
||||
// } catch {
|
||||
// console.log("Exception thrown.. ");
|
||||
// }
|
||||
// }
|
||||
|
||||
console.log("nft bridge booted");
|
||||
|
||||
|
|
|
@ -51,9 +51,7 @@ async function initNear() {
|
|||
keyStore.setKey(config.networkId, config.portalAccount, portalMasterKey);
|
||||
|
||||
let near = await nearAPI.connect({
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: config.networkId,
|
||||
nodeUrl: config.nodeUrl,
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"env-cmd": "^10.1.0",
|
||||
"ethers": "^5.6.5",
|
||||
"near-api-js": "^0.43.1",
|
||||
"near-seed-phrase": "^0.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
@ -35,7 +36,6 @@
|
|||
"@types/prompt": "^1.1.2",
|
||||
"cssnano": "^5.0.7",
|
||||
"gh-pages": "^3.1.0",
|
||||
"near-seed-phrase": "^0.2.0",
|
||||
"parcel-bundler": "^1.12.5",
|
||||
"postcss": "^8.3.6",
|
||||
"prompt": "^1.3.0",
|
||||
|
@ -44,11 +44,12 @@
|
|||
},
|
||||
"../sdk/js": {
|
||||
"name": "@certusone/wormhole-sdk",
|
||||
"version": "0.6.2",
|
||||
"version": "0.6.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@certusone/wormhole-sdk-proto-web": "^0.0.3",
|
||||
"@certusone/wormhole-sdk-proto-web": "^0.0.5",
|
||||
"@certusone/wormhole-sdk-wasm": "^0.0.1",
|
||||
"@injectivelabs/sdk-ts": "^1.0.75",
|
||||
"@solana/spl-token": "^0.1.8",
|
||||
"@solana/web3.js": "^1.24.0",
|
||||
"@terra-money/terra.js": "^3.1.3",
|
||||
|
@ -56,10 +57,12 @@
|
|||
"axios": "^0.24.0",
|
||||
"bech32": "^2.0.0",
|
||||
"js-base64": "^3.6.1",
|
||||
"near-api-js": "^0.45.1"
|
||||
"near-api-js": "^0.44.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
||||
"@injectivelabs/networks": "^1.0.12",
|
||||
"@injectivelabs/tx-ts": "^1.0.22",
|
||||
"@openzeppelin/contracts": "^4.2.0",
|
||||
"@typechain/ethers-v5": "^7.0.1",
|
||||
"@types/jest": "^27.0.2",
|
||||
|
@ -3319,7 +3322,6 @@
|
|||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz",
|
||||
"integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "11.11.6",
|
||||
"create-hash": "^1.1.0",
|
||||
|
@ -3331,7 +3333,6 @@
|
|||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/bip39-light/-/bip39-light-1.0.7.tgz",
|
||||
"integrity": "sha512-WDTmLRQUsiioBdTs9BmSEmkJza+8xfJmptsNJjxnoq3EydSa/ZBXT6rm66KoT3PJIRYMnhSKNR7S9YL1l7R40Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"create-hash": "^1.1.0",
|
||||
"pbkdf2": "^3.0.9"
|
||||
|
@ -3340,8 +3341,7 @@
|
|||
"node_modules/bip39/node_modules/@types/node": {
|
||||
"version": "11.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz",
|
||||
"integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ=="
|
||||
},
|
||||
"node_modules/blakejs": {
|
||||
"version": "1.2.1",
|
||||
|
@ -9180,7 +9180,6 @@
|
|||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/near-hd-key/-/near-hd-key-1.2.1.tgz",
|
||||
"integrity": "sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bip39": "3.0.2",
|
||||
"create-hmac": "1.1.7",
|
||||
|
@ -9191,7 +9190,6 @@
|
|||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/near-seed-phrase/-/near-seed-phrase-0.2.0.tgz",
|
||||
"integrity": "sha512-NpmrnejpY1AdlRpDZ0schJQJtfBaoUheRfiYtQpcq9TkwPgqKZCRULV5L3hHmLc0ep7KRtikbPQ9R2ztN/3cyQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bip39-light": "^1.0.7",
|
||||
"bs58": "^4.0.1",
|
||||
|
@ -9203,7 +9201,6 @@
|
|||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
|
||||
"integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
|
@ -9212,7 +9209,6 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
||||
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"base-x": "^3.0.2"
|
||||
}
|
||||
|
@ -16625,9 +16621,12 @@
|
|||
"@certusone/wormhole-sdk": {
|
||||
"version": "file:../sdk/js",
|
||||
"requires": {
|
||||
"@certusone/wormhole-sdk-proto-web": "^0.0.3",
|
||||
"@certusone/wormhole-sdk-proto-web": "^0.0.5",
|
||||
"@certusone/wormhole-sdk-wasm": "^0.0.1",
|
||||
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
||||
"@injectivelabs/networks": "^1.0.12",
|
||||
"@injectivelabs/sdk-ts": "^1.0.75",
|
||||
"@injectivelabs/tx-ts": "^1.0.22",
|
||||
"@openzeppelin/contracts": "^4.2.0",
|
||||
"@solana/spl-token": "^0.1.8",
|
||||
"@solana/web3.js": "^1.24.0",
|
||||
|
@ -16644,7 +16643,7 @@
|
|||
"ethers": "^5.6.8",
|
||||
"jest": "^27.3.1",
|
||||
"js-base64": "^3.6.1",
|
||||
"near-api-js": "^0.45.1",
|
||||
"near-api-js": "^0.44.2",
|
||||
"prettier": "^2.3.2",
|
||||
"ts-jest": "^27.0.7",
|
||||
"tslint": "^6.1.3",
|
||||
|
@ -17742,7 +17741,6 @@
|
|||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz",
|
||||
"integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "11.11.6",
|
||||
"create-hash": "^1.1.0",
|
||||
|
@ -17753,8 +17751,7 @@
|
|||
"@types/node": {
|
||||
"version": "11.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz",
|
||||
"integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -17762,7 +17759,6 @@
|
|||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/bip39-light/-/bip39-light-1.0.7.tgz",
|
||||
"integrity": "sha512-WDTmLRQUsiioBdTs9BmSEmkJza+8xfJmptsNJjxnoq3EydSa/ZBXT6rm66KoT3PJIRYMnhSKNR7S9YL1l7R40Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"create-hash": "^1.1.0",
|
||||
"pbkdf2": "^3.0.9"
|
||||
|
@ -22478,7 +22474,6 @@
|
|||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/near-hd-key/-/near-hd-key-1.2.1.tgz",
|
||||
"integrity": "sha512-SIrthcL5Wc0sps+2e1xGj3zceEa68TgNZDLuCx0daxmfTP7sFTB3/mtE2pYhlFsCxWoMn+JfID5E1NlzvvbRJg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bip39": "3.0.2",
|
||||
"create-hmac": "1.1.7",
|
||||
|
@ -22489,7 +22484,6 @@
|
|||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/near-seed-phrase/-/near-seed-phrase-0.2.0.tgz",
|
||||
"integrity": "sha512-NpmrnejpY1AdlRpDZ0schJQJtfBaoUheRfiYtQpcq9TkwPgqKZCRULV5L3hHmLc0ep7KRtikbPQ9R2ztN/3cyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bip39-light": "^1.0.7",
|
||||
"bs58": "^4.0.1",
|
||||
|
@ -22501,7 +22495,6 @@
|
|||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
|
||||
"integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
|
@ -22510,7 +22503,6 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
||||
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base-x": "^3.0.2"
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"env-cmd": "^10.1.0",
|
||||
"ethers": "^5.6.5",
|
||||
"near-api-js": "^0.43.1",
|
||||
"near-seed-phrase": "^0.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
@ -38,7 +39,6 @@
|
|||
"@types/prompt": "^1.1.2",
|
||||
"cssnano": "^5.0.7",
|
||||
"gh-pages": "^3.1.0",
|
||||
"near-seed-phrase": "^0.2.0",
|
||||
"parcel-bundler": "^1.12.5",
|
||||
"postcss": "^8.3.6",
|
||||
"prompt": "^1.3.0",
|
||||
|
|
|
@ -18,14 +18,13 @@ import {
|
|||
} from "@certusone/wormhole-sdk/node_modules/near-api-js";
|
||||
|
||||
import {
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_NEAR,
|
||||
CONTRACTS,
|
||||
attestTokenFromNear,
|
||||
getSignedVAAWithRetry,
|
||||
hexToUint8Array,
|
||||
transferTokenFromNear,
|
||||
uint8ArrayToHex,
|
||||
parseSequenceFromLogNear,
|
||||
getEmitterAddressNear,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
|
||||
// @ts-ignore
|
||||
|
@ -75,17 +74,12 @@ async function transferTest() {
|
|||
// connect to near...
|
||||
let near = await nearConnect({
|
||||
headers: {},
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: networkId as string,
|
||||
nodeUrl: nearNodeUrl as string,
|
||||
});
|
||||
|
||||
console.log(
|
||||
"Attesting",
|
||||
NEAR_TOKEN_ADDRESS,
|
||||
);
|
||||
console.log("Attesting", NEAR_TOKEN_ADDRESS);
|
||||
|
||||
prompt.message = "";
|
||||
const { input } = await prompt.get({
|
||||
|
@ -104,20 +98,30 @@ async function transferTest() {
|
|||
near.connection,
|
||||
process.env.NEAR_ACCOUNT as string
|
||||
);
|
||||
const provider = near.connection.provider;
|
||||
|
||||
let [sequence, emitterAddress] = await attestTokenFromNear(
|
||||
userAccount,
|
||||
const attestMsgs = await attestTokenFromNear(
|
||||
provider,
|
||||
CONTRACTS.MAINNET.near.core,
|
||||
CONTRACTS.MAINNET.near.token_bridge,
|
||||
NEAR_TOKEN_ADDRESS
|
||||
);
|
||||
|
||||
if (sequence === -1) {
|
||||
let attestOutcome;
|
||||
for (const msg of attestMsgs) {
|
||||
attestOutcome = await userAccount.functionCall(msg);
|
||||
}
|
||||
const sequence = parseSequenceFromLogNear(attestOutcome);
|
||||
if (sequence === null) {
|
||||
console.log("No sequence found, check above for error");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log("emitterAddress:", emitterAddress, "sequence:", sequence);
|
||||
console.log(
|
||||
"emitterAddress:",
|
||||
getEmitterAddressNear(CONTRACTS.MAINNET.near.token_bridge),
|
||||
"sequence:",
|
||||
sequence
|
||||
);
|
||||
|
||||
console.log(
|
||||
`If this script hangs, try https://wormhole-v2-mainnet-api.certus.one/v1/signed_vaa/15/${emitterAddress}/${sequence.toString()}`
|
||||
|
@ -126,8 +130,8 @@ async function transferTest() {
|
|||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
WORMHOLE_RPC_HOSTS,
|
||||
CHAIN_ID_NEAR,
|
||||
emitterAddress,
|
||||
sequence.toString(),
|
||||
getEmitterAddressNear(CONTRACTS.MAINNET.near.token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
|
|
@ -81,9 +81,7 @@ async function transferTest() {
|
|||
// connect to near...
|
||||
let near = await nearConnect({
|
||||
headers: {},
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: networkId as string,
|
||||
nodeUrl: nearNodeUrl as string,
|
||||
});
|
||||
|
@ -129,8 +127,8 @@ async function transferTest() {
|
|||
console.log("account already registered");
|
||||
}
|
||||
|
||||
// like this
|
||||
await redeemOnNear(userAccount, token_bridge, hexToUint8Array(trans))
|
||||
// like this
|
||||
await redeemOnNear(userAccount, token_bridge, hexToUint8Array(trans));
|
||||
}
|
||||
|
||||
transferTest();
|
||||
|
|
|
@ -1,46 +1,16 @@
|
|||
const nearAPI = require("near-api-js");
|
||||
const BN = require("bn.js");
|
||||
const fs = require("fs");
|
||||
const fetch = require("node-fetch");
|
||||
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
|
||||
|
||||
import {
|
||||
CONTRACTS,
|
||||
attestNearFromNear,
|
||||
attestTokenFromNear,
|
||||
attestFromAlgorand,
|
||||
createWrappedOnAlgorand,
|
||||
tryNativeToUint8Array,
|
||||
createWrappedOnNear,
|
||||
getEmitterAddressAlgorand,
|
||||
getForeignAssetAlgorand,
|
||||
getForeignAssetNear,
|
||||
getIsTransferCompletedNear,
|
||||
getIsWrappedAssetNear,
|
||||
getOriginalAssetNear,
|
||||
getSignedVAAWithRetry,
|
||||
redeemOnAlgorand,
|
||||
redeemOnNear,
|
||||
transferFromAlgorand,
|
||||
transferNearFromNear,
|
||||
transferTokenFromNear,
|
||||
parseSequenceFromLogNear,
|
||||
getEmitterAddressNear,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
|
||||
const wh = require("@certusone/wormhole-sdk");
|
||||
|
||||
import {
|
||||
CHAIN_ID_ALGORAND,
|
||||
CHAIN_ID_NEAR,
|
||||
ChainId,
|
||||
ChainName,
|
||||
textToHexString,
|
||||
textToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/utils";
|
||||
|
||||
import {
|
||||
_parseVAAAlgorand,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/algorand";
|
||||
|
||||
import { _parseVAAAlgorand } from "@certusone/wormhole-sdk/lib/cjs/algorand";
|
||||
|
||||
function getConfig(env: any) {
|
||||
switch (env) {
|
||||
|
@ -77,7 +47,6 @@ async function initNear() {
|
|||
let masterKey = nearAPI.utils.KeyPair.fromString(
|
||||
"ed25519:5dJ7Nsq4DQBdiGvZLPyjRVmhtRaScahsREpEPtaAyE9Z3CgyZFsaBwpybCRBMugiwhbFCUkqHk7PJ3BVcgZZ9Lgk"
|
||||
);
|
||||
let masterPubKey = masterKey.getPublicKey();
|
||||
|
||||
let keyStore = new nearAPI.keyStores.InMemoryKeyStore();
|
||||
keyStore.setKey(config.networkId, config.masterAccount, masterKey);
|
||||
|
@ -93,6 +62,7 @@ async function initNear() {
|
|||
near.connection,
|
||||
config.masterAccount
|
||||
);
|
||||
const provider = near.connection.provider;
|
||||
|
||||
console.log(
|
||||
"Finish init NEAR masterAccount: " +
|
||||
|
@ -114,13 +84,22 @@ async function initNear() {
|
|||
);
|
||||
|
||||
console.log("attesting Near itself");
|
||||
let s = await attestNearFromNear(masterAccount, core_bridge, token_bridge);
|
||||
const attestMsg = await attestNearFromNear(
|
||||
provider,
|
||||
core_bridge,
|
||||
token_bridge
|
||||
);
|
||||
const attestOutcome = await masterAccount.functionCall(attestMsg);
|
||||
const attestSeq = parseSequenceFromLogNear(attestOutcome);
|
||||
if (attestSeq === null) {
|
||||
throw new Error("attestSeq is null");
|
||||
}
|
||||
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["https://wormhole-v2-testnet-api.certus.one"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
"near",
|
||||
getEmitterAddressNear(token_bridge),
|
||||
attestSeq,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -128,21 +107,29 @@ async function initNear() {
|
|||
|
||||
console.log("vaa: " + Buffer.from(signedVAA).toString("hex"));
|
||||
|
||||
s = await transferNearFromNear(
|
||||
masterAccount,
|
||||
const transferMsg = await transferNearFromNear(
|
||||
provider,
|
||||
core_bridge,
|
||||
token_bridge,
|
||||
BigInt(1000000000000000000000000),
|
||||
tryNativeToUint8Array("0x3bC7f2e458aC4E55F941C458cfD8c6851a591B4F", "ethereum"),
|
||||
tryNativeToUint8Array(
|
||||
"0x3bC7f2e458aC4E55F941C458cfD8c6851a591B4F",
|
||||
"ethereum"
|
||||
),
|
||||
2,
|
||||
BigInt(0)
|
||||
);
|
||||
const transferOutcome = await masterAccount.functionCall(transferMsg);
|
||||
const transferSeq = parseSequenceFromLogNear(transferOutcome);
|
||||
if (transferSeq === null) {
|
||||
throw new Error("transferSeq is null");
|
||||
}
|
||||
|
||||
const { vaaBytes: signedTrans } = await getSignedVAAWithRetry(
|
||||
["https://wormhole-v2-testnet-api.certus.one"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
"near",
|
||||
getEmitterAddressNear(token_bridge),
|
||||
transferSeq,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -150,8 +137,8 @@ async function initNear() {
|
|||
|
||||
console.log("vaa: " + Buffer.from(signedTrans).toString("hex"));
|
||||
|
||||
let p = _parseVAAAlgorand(signedTrans);
|
||||
console.log(p);
|
||||
let p = _parseVAAAlgorand(signedTrans);
|
||||
console.log(p);
|
||||
}
|
||||
|
||||
initNear();
|
||||
|
|
107
near/test/p3.ts
107
near/test/p3.ts
|
@ -1,39 +1,20 @@
|
|||
// npx pretty-quick
|
||||
|
||||
const sha256 = require("js-sha256");
|
||||
const nearAPI = require("near-api-js");
|
||||
const fs = require("fs").promises;
|
||||
const assert = require("assert").strict;
|
||||
const fetch = require("node-fetch");
|
||||
const elliptic = require("elliptic");
|
||||
const web3Utils = require("web3-utils");
|
||||
import { zeroPad } from "@ethersproject/bytes";
|
||||
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
|
||||
|
||||
import { Account as nearAccount } from "@certusone/wormhole-sdk/node_modules/near-api-js";
|
||||
const BN = require("bn.js");
|
||||
|
||||
import { TestLib } from "./testlib";
|
||||
|
||||
import algosdk, {
|
||||
Account,
|
||||
Algodv2,
|
||||
OnApplicationComplete,
|
||||
SuggestedParams,
|
||||
bigIntToBytes,
|
||||
decodeAddress,
|
||||
getApplicationAddress,
|
||||
makeApplicationCallTxnFromObject,
|
||||
makePaymentTxnWithSuggestedParamsFromObject,
|
||||
waitForConfirmation,
|
||||
} from "@certusone/wormhole-sdk/node_modules/algosdk";
|
||||
|
||||
import {
|
||||
createAsset,
|
||||
getAlgoClient,
|
||||
getBalance,
|
||||
getBalances,
|
||||
getForeignAssetFromVaaAlgorand,
|
||||
getTempAccounts,
|
||||
signSendAndConfirmAlgorand,
|
||||
} from "./algoHelpers";
|
||||
|
@ -42,44 +23,28 @@ import {
|
|||
CHAIN_ID_ALGORAND,
|
||||
CHAIN_ID_NEAR,
|
||||
ChainId,
|
||||
ChainName,
|
||||
textToHexString,
|
||||
textToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/utils";
|
||||
|
||||
import { safeBigIntToNumber } from "@certusone/wormhole-sdk/lib/cjs/utils/bigint";
|
||||
|
||||
import {
|
||||
CONTRACTS,
|
||||
attestNearFromNear,
|
||||
attestTokenFromNear,
|
||||
attestFromAlgorand,
|
||||
createWrappedOnAlgorand,
|
||||
createWrappedOnNear,
|
||||
getEmitterAddressAlgorand,
|
||||
getForeignAssetAlgorand,
|
||||
getForeignAssetNear,
|
||||
getIsTransferCompletedNear,
|
||||
getIsWrappedAssetNear,
|
||||
getOriginalAssetNear,
|
||||
getSignedVAAWithRetry,
|
||||
redeemOnAlgorand,
|
||||
redeemOnNear,
|
||||
transferFromAlgorand,
|
||||
transferNearFromNear,
|
||||
transferTokenFromNear,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
|
||||
const wh = require("@certusone/wormhole-sdk");
|
||||
|
||||
import { parseSequenceFromLogAlgorand } from "@certusone/wormhole-sdk/lib/cjs/bridge";
|
||||
|
||||
import { _parseVAAAlgorand } from "@certusone/wormhole-sdk/lib/cjs/algorand";
|
||||
import {
|
||||
getMessageFee,
|
||||
optin,
|
||||
TransactionSignerPair,
|
||||
_parseVAAAlgorand,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/algorand";
|
||||
getEmitterAddressNear,
|
||||
parseSequenceFromLogNear,
|
||||
} from "@certusone/wormhole-sdk/src";
|
||||
|
||||
export const uint8ArrayToHex = (a: Uint8Array): string =>
|
||||
Buffer.from(a).toString("hex");
|
||||
|
@ -131,21 +96,6 @@ export function logNearGas(result: any, comment: string) {
|
|||
);
|
||||
}
|
||||
|
||||
export function parseSequenceFromLogNear(result: any): [number, string] {
|
||||
let sequence = "";
|
||||
for (const o of result.receipts_outcome) {
|
||||
for (const l of o.outcome.logs) {
|
||||
if (l.startsWith("EVENT_JSON:")) {
|
||||
const body = JSON.parse(l.slice(11));
|
||||
if (body.standard == "wormhole" && body.event == "publish") {
|
||||
return [body.seq, body.emitter];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [-1, ""];
|
||||
}
|
||||
|
||||
async function testNearSDK() {
|
||||
let config = getConfig(process.env.NEAR_ENV || "sandbox");
|
||||
|
||||
|
@ -157,7 +107,6 @@ async function testNearSDK() {
|
|||
let masterKey = nearAPI.utils.KeyPair.fromString(
|
||||
keyFile.secret_key || keyFile.private_key
|
||||
);
|
||||
let masterPubKey = masterKey.getPublicKey();
|
||||
|
||||
let keyStore = new nearAPI.keyStores.InMemoryKeyStore();
|
||||
keyStore.setKey(config.networkId, config.masterAccount, masterKey);
|
||||
|
@ -197,6 +146,7 @@ async function testNearSDK() {
|
|||
new BN(10).pow(new BN(27))
|
||||
);
|
||||
const userAccount = new nearAPI.Account(near.connection, config.userAccount);
|
||||
const provider = near.connection.provider;
|
||||
|
||||
console.log(
|
||||
"creating a second user account: " +
|
||||
|
@ -223,13 +173,8 @@ async function testNearSDK() {
|
|||
let algoCore = BigInt(CONTRACTS.DEVNET.algorand.core);
|
||||
let algoToken = BigInt(CONTRACTS.DEVNET.algorand.token_bridge);
|
||||
|
||||
const tbAddr: string = getApplicationAddress(algoToken);
|
||||
const decTbAddr: Uint8Array = decodeAddress(tbAddr).publicKey;
|
||||
const aa: string = uint8ArrayToHex(decTbAddr);
|
||||
|
||||
const algoClient: algosdk.Algodv2 = getAlgoClient();
|
||||
const tempAccts: Account[] = await getTempAccounts();
|
||||
const numAccts: number = tempAccts.length;
|
||||
|
||||
const algoWallet: Account = tempAccts[0];
|
||||
|
||||
|
@ -253,9 +198,16 @@ async function testNearSDK() {
|
|||
|
||||
seq = seq + 1;
|
||||
|
||||
let usdcp = _parseVAAAlgorand(usdcvaa);
|
||||
|
||||
let usdc = await createWrappedOnNear(userAccount, token_bridge, usdcvaa);
|
||||
const createWrappedMsgs = await createWrappedOnNear(
|
||||
provider,
|
||||
token_bridge,
|
||||
usdcvaa
|
||||
);
|
||||
let usdc;
|
||||
for (const msg of createWrappedMsgs) {
|
||||
const tx = await userAccount.functionCall(msg);
|
||||
usdc = nearAPI.providers.getTransactionLastResult(tx);
|
||||
}
|
||||
console.log(usdc);
|
||||
|
||||
console.log("Creating USDC token on algorand");
|
||||
|
@ -298,7 +250,12 @@ async function testNearSDK() {
|
|||
console.log(trans);
|
||||
|
||||
console.log(
|
||||
await redeemOnNear(userAccount, token_bridge, hexToUint8Array(trans))
|
||||
await redeemOnNear(
|
||||
provider,
|
||||
userAccount.account_id,
|
||||
token_bridge,
|
||||
hexToUint8Array(trans)
|
||||
)
|
||||
);
|
||||
}
|
||||
console.log(".. created some USDC on near");
|
||||
|
@ -306,8 +263,9 @@ async function testNearSDK() {
|
|||
let wrappedTransfer;
|
||||
{
|
||||
console.log("transfer USDC from near to algorand");
|
||||
let s = await transferTokenFromNear(
|
||||
userAccount,
|
||||
const transferMsg = await transferTokenFromNear(
|
||||
provider,
|
||||
userAccount.account_id,
|
||||
core_bridge,
|
||||
token_bridge,
|
||||
usdc,
|
||||
|
@ -316,12 +274,18 @@ async function testNearSDK() {
|
|||
8,
|
||||
BigInt(0)
|
||||
);
|
||||
const transferOutcome = await userAccount.functionCall(transferMsg);
|
||||
const sequence = parseSequenceFromLogNear(transferOutcome);
|
||||
if (sequence === null) {
|
||||
console.log("sequence is null");
|
||||
return;
|
||||
}
|
||||
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["http://localhost:7071"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
getEmitterAddressNear(token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -407,7 +371,12 @@ async function testNearSDK() {
|
|||
|
||||
console.log("redeeming P3 NEAR on Near");
|
||||
console.log(
|
||||
await redeemOnNear(user2Account, token_bridge, transferAlgoToNearP3)
|
||||
await redeemOnNear(
|
||||
provider,
|
||||
user2Account.account_id,
|
||||
token_bridge,
|
||||
transferAlgoToNearP3
|
||||
)
|
||||
);
|
||||
|
||||
console.log("transfering USDC from Algo To Near... getting the vaa");
|
||||
|
|
253
near/test/sdk.ts
253
near/test/sdk.ts
|
@ -1,12 +1,6 @@
|
|||
// npx pretty-quick
|
||||
|
||||
const sha256 = require("js-sha256");
|
||||
const fs = require("fs").promises;
|
||||
const assert = require("assert").strict;
|
||||
const fetch = require("node-fetch");
|
||||
const elliptic = require("elliptic");
|
||||
const web3Utils = require("web3-utils");
|
||||
import { zeroPad } from "@ethersproject/bytes";
|
||||
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
|
||||
|
||||
import {
|
||||
|
@ -23,22 +17,12 @@ import { TestLib } from "./testlib";
|
|||
|
||||
import algosdk, {
|
||||
Account,
|
||||
Algodv2,
|
||||
OnApplicationComplete,
|
||||
SuggestedParams,
|
||||
bigIntToBytes,
|
||||
decodeAddress,
|
||||
getApplicationAddress,
|
||||
makeApplicationCallTxnFromObject,
|
||||
makePaymentTxnWithSuggestedParamsFromObject,
|
||||
waitForConfirmation,
|
||||
} from "@certusone/wormhole-sdk/node_modules/algosdk";
|
||||
|
||||
import {
|
||||
getAlgoClient,
|
||||
getBalance,
|
||||
getBalances,
|
||||
getForeignAssetFromVaaAlgorand,
|
||||
getTempAccounts,
|
||||
signSendAndConfirmAlgorand,
|
||||
} from "./algoHelpers";
|
||||
|
@ -47,13 +31,8 @@ import {
|
|||
CHAIN_ID_ALGORAND,
|
||||
CHAIN_ID_NEAR,
|
||||
ChainId,
|
||||
ChainName,
|
||||
textToHexString,
|
||||
textToUint8Array,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/utils";
|
||||
|
||||
import { safeBigIntToNumber } from "@certusone/wormhole-sdk/lib/cjs/utils/bigint";
|
||||
|
||||
import {
|
||||
CONTRACTS,
|
||||
attestNearFromNear,
|
||||
|
@ -66,8 +45,6 @@ import {
|
|||
getForeignAssetAlgorand,
|
||||
getForeignAssetNear,
|
||||
getIsTransferCompletedNear,
|
||||
getIsWrappedAssetNear,
|
||||
getOriginalAssetNear,
|
||||
getSignedVAAWithRetry,
|
||||
redeemOnAlgorand,
|
||||
redeemOnNear,
|
||||
|
@ -76,19 +53,10 @@ import {
|
|||
transferTokenFromNear,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
|
||||
const wh = require("@certusone/wormhole-sdk");
|
||||
import { parseSequenceFromLogAlgorand } from "@certusone/wormhole-sdk/lib/cjs/bridge";
|
||||
|
||||
import {
|
||||
parseSequenceFromLogAlgorand,
|
||||
parseSequenceFromLogNear,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/bridge";
|
||||
|
||||
import {
|
||||
getMessageFee,
|
||||
optin,
|
||||
TransactionSignerPair,
|
||||
_parseVAAAlgorand,
|
||||
} from "@certusone/wormhole-sdk/lib/cjs/algorand";
|
||||
import { _parseVAAAlgorand } from "@certusone/wormhole-sdk/lib/cjs/algorand";
|
||||
import { parseSequenceFromLogNear } from "@certusone/wormhole-sdk/src";
|
||||
|
||||
export const uint8ArrayToHex = (a: Uint8Array): string =>
|
||||
Buffer.from(a).toString("hex");
|
||||
|
@ -218,7 +186,6 @@ async function testNearSDK() {
|
|||
let masterKey = nearUtils.KeyPair.fromString(
|
||||
keyFile.secret_key || keyFile.private_key
|
||||
);
|
||||
let masterPubKey = masterKey.getPublicKey();
|
||||
|
||||
let keyStore = new nearKeyStores.InMemoryKeyStore();
|
||||
keyStore.setKey(
|
||||
|
@ -229,9 +196,7 @@ async function testNearSDK() {
|
|||
|
||||
let near = await nearConnect({
|
||||
headers: {},
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: config.networkId as string,
|
||||
nodeUrl: config.nodeUrl as string,
|
||||
});
|
||||
|
@ -274,6 +239,7 @@ async function testNearSDK() {
|
|||
near.connection,
|
||||
config.userAccount as string
|
||||
);
|
||||
const provider = near.connection.provider;
|
||||
|
||||
console.log(
|
||||
"creating a second user account: " +
|
||||
|
@ -317,11 +283,9 @@ async function testNearSDK() {
|
|||
|
||||
const tbAddr: string = getApplicationAddress(algoToken);
|
||||
const decTbAddr: Uint8Array = decodeAddress(tbAddr).publicKey;
|
||||
const aa: string = uint8ArrayToHex(decTbAddr);
|
||||
|
||||
const algoClient: algosdk.Algodv2 = getAlgoClient();
|
||||
const tempAccts: Account[] = await getTempAccounts();
|
||||
const numAccts: number = tempAccts.length;
|
||||
|
||||
const algoWallet: Account = tempAccts[0];
|
||||
|
||||
|
@ -353,12 +317,15 @@ async function testNearSDK() {
|
|||
{ transport: NodeHttpTransport() }
|
||||
);
|
||||
|
||||
let noriumNear = await createWrappedOnNear(
|
||||
userAccount,
|
||||
for (const msg of await createWrappedOnNear(
|
||||
provider,
|
||||
token_bridge,
|
||||
vaaBytes
|
||||
);
|
||||
console.log("for norium, createWrappedOnNear returned " + noriumNear);
|
||||
)) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
|
||||
console.log("for norium, createWrappedOnNear returned");
|
||||
|
||||
let account_hash = await userAccount.viewFunction(
|
||||
token_bridge,
|
||||
|
@ -455,14 +422,22 @@ async function testNearSDK() {
|
|||
console.log("calling createWrappedOnNear to create usdc");
|
||||
|
||||
if (
|
||||
(await getIsTransferCompletedNear(userAccount, token_bridge, usdcvaa)) ==
|
||||
true
|
||||
(await getIsTransferCompletedNear(provider, token_bridge, usdcvaa)) == true
|
||||
) {
|
||||
console.log("getIsTransferCompleted returned incorrect value (true)");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let usdc = await createWrappedOnNear(userAccount, token_bridge, usdcvaa);
|
||||
const createWrappedMsgs = await createWrappedOnNear(
|
||||
provider,
|
||||
token_bridge,
|
||||
usdcvaa
|
||||
);
|
||||
let usdc;
|
||||
for (const msg of createWrappedMsgs) {
|
||||
const tx = await userAccount.functionCall(msg);
|
||||
usdc = nearProviders.getTransactionLastResult(tx);
|
||||
}
|
||||
console.log("createWrappedOnNear returned " + usdc);
|
||||
|
||||
if (usdc === "") {
|
||||
|
@ -471,15 +446,14 @@ async function testNearSDK() {
|
|||
}
|
||||
|
||||
if (
|
||||
(await getIsTransferCompletedNear(userAccount, token_bridge, usdcvaa)) ==
|
||||
false
|
||||
(await getIsTransferCompletedNear(provider, token_bridge, usdcvaa)) == false
|
||||
) {
|
||||
console.log("getIsTransferCompleted returned incorrect value (false)");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let aname = await getForeignAssetNear(
|
||||
userAccount,
|
||||
provider,
|
||||
token_bridge,
|
||||
usdcp.FromChain as ChainId,
|
||||
usdcp.Contract as string
|
||||
|
@ -518,9 +492,15 @@ async function testNearSDK() {
|
|||
console.log(trans);
|
||||
|
||||
try {
|
||||
console.log(
|
||||
await redeemOnNear(userAccount, token_bridge, hexToUint8Array(trans))
|
||||
const redeemMsgs = await redeemOnNear(
|
||||
provider,
|
||||
userAccount.accountId,
|
||||
token_bridge,
|
||||
hexToUint8Array(trans)
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
console.log("This should have thrown a exception..");
|
||||
process.exit(1);
|
||||
} catch (error) {
|
||||
|
@ -541,30 +521,52 @@ async function testNearSDK() {
|
|||
);
|
||||
console.log("myAddress: " + myAddress2);
|
||||
|
||||
console.log(
|
||||
await redeemOnNear(userAccount, token_bridge, hexToUint8Array(trans))
|
||||
const redeemMsgs = await redeemOnNear(
|
||||
provider,
|
||||
userAccount.accountId,
|
||||
token_bridge,
|
||||
hexToUint8Array(trans)
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
}
|
||||
console.log(".. created some USDC");
|
||||
|
||||
console.log("Redeeming norium on near");
|
||||
await redeemOnNear(userAccount, token_bridge, signedVaa.vaaBytes);
|
||||
for (const msg of await redeemOnNear(
|
||||
provider,
|
||||
userAccount.accountId,
|
||||
token_bridge,
|
||||
signedVaa.vaaBytes
|
||||
)) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
|
||||
let nativeAttest;
|
||||
{
|
||||
console.log("attesting: " + randoToken);
|
||||
let s = await attestTokenFromNear(
|
||||
userAccount,
|
||||
const attestMsgs = await attestTokenFromNear(
|
||||
provider,
|
||||
core_bridge,
|
||||
token_bridge,
|
||||
randoToken
|
||||
);
|
||||
console.log(s);
|
||||
let sequence;
|
||||
for (const msg of attestMsgs) {
|
||||
const tx = await userAccount.functionCall(msg);
|
||||
sequence = parseSequenceFromLogNear(tx);
|
||||
}
|
||||
if (!sequence) {
|
||||
console.log("sequence is null");
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(getEmitterAddressNear(token_bridge));
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["http://localhost:7071"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
getEmitterAddressNear(token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -576,7 +578,7 @@ async function testNearSDK() {
|
|||
console.log(p.FromChain as ChainId, p.Contract as string);
|
||||
|
||||
let a = await getForeignAssetNear(
|
||||
userAccount,
|
||||
provider,
|
||||
token_bridge,
|
||||
p.FromChain as ChainId,
|
||||
p.Contract as string
|
||||
|
@ -592,13 +594,22 @@ async function testNearSDK() {
|
|||
let nearAttest;
|
||||
{
|
||||
console.log("attesting Near itself");
|
||||
let s = await attestNearFromNear(userAccount, core_bridge, token_bridge);
|
||||
|
||||
const attestMsg = await attestNearFromNear(
|
||||
provider,
|
||||
core_bridge,
|
||||
token_bridge
|
||||
);
|
||||
const tx = await userAccount.functionCall(attestMsg);
|
||||
const sequence = parseSequenceFromLogNear(tx);
|
||||
if (sequence === null) {
|
||||
console.log("sequence is null");
|
||||
process.exit(1);
|
||||
}
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["http://localhost:7071"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
getEmitterAddressNear(token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -607,7 +618,7 @@ async function testNearSDK() {
|
|||
console.log("vaa: " + Buffer.from(signedVAA).toString("hex"));
|
||||
let p = _parseVAAAlgorand(signedVAA);
|
||||
let a = await getForeignAssetNear(
|
||||
userAccount,
|
||||
provider,
|
||||
token_bridge,
|
||||
p.FromChain as ChainId,
|
||||
p.Contract as string
|
||||
|
@ -658,8 +669,9 @@ async function testNearSDK() {
|
|||
usdc
|
||||
);
|
||||
|
||||
let s = await transferTokenFromNear(
|
||||
userAccount,
|
||||
const transferMsgs = await transferTokenFromNear(
|
||||
provider,
|
||||
userAccount.accountId,
|
||||
core_bridge,
|
||||
token_bridge,
|
||||
usdc,
|
||||
|
@ -668,12 +680,21 @@ async function testNearSDK() {
|
|||
8,
|
||||
BigInt(0)
|
||||
);
|
||||
let sequence;
|
||||
for (const msg of transferMsgs) {
|
||||
const tx = await userAccount.functionCall(msg);
|
||||
sequence = parseSequenceFromLogNear(tx);
|
||||
}
|
||||
if (!sequence) {
|
||||
console.log("sequence is null");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["http://localhost:7071"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
getEmitterAddressNear(token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -698,8 +719,9 @@ async function testNearSDK() {
|
|||
let randoTransfer;
|
||||
{
|
||||
console.log("YYY transfer rando token from near to algorand");
|
||||
let s = await transferTokenFromNear(
|
||||
userAccount,
|
||||
const transferMsgs = await transferTokenFromNear(
|
||||
provider,
|
||||
userAccount.accountId,
|
||||
core_bridge,
|
||||
token_bridge,
|
||||
randoToken,
|
||||
|
@ -708,12 +730,21 @@ async function testNearSDK() {
|
|||
8,
|
||||
BigInt(0)
|
||||
);
|
||||
let sequence;
|
||||
for (const msg of transferMsgs) {
|
||||
const tx = await userAccount.functionCall(msg);
|
||||
sequence = parseSequenceFromLogNear(tx);
|
||||
}
|
||||
if (!sequence) {
|
||||
console.log("sequence is null");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["http://localhost:7071"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
getEmitterAddressNear(token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -723,16 +754,6 @@ async function testNearSDK() {
|
|||
randoTransfer = signedVAA;
|
||||
|
||||
console.log(_parseVAAAlgorand(randoTransfer));
|
||||
|
||||
if (s[1] != getEmitterAddressNear(token_bridge)) {
|
||||
console.log(
|
||||
"Unexpected emitter address: " +
|
||||
s[1] +
|
||||
"!=" +
|
||||
getEmitterAddressNear(token_bridge)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
|
@ -750,8 +771,8 @@ async function testNearSDK() {
|
|||
let nearTransfer;
|
||||
{
|
||||
console.log("transfer near from near to algorand");
|
||||
let s = await transferNearFromNear(
|
||||
userAccount,
|
||||
const transferMsg = await transferNearFromNear(
|
||||
provider,
|
||||
core_bridge,
|
||||
token_bridge,
|
||||
BigInt(1000000000000000000000000),
|
||||
|
@ -759,12 +780,18 @@ async function testNearSDK() {
|
|||
8,
|
||||
BigInt(0)
|
||||
);
|
||||
const tx = await userAccount.functionCall(transferMsg);
|
||||
const sequence = parseSequenceFromLogNear(tx);
|
||||
if (sequence === null) {
|
||||
console.log("sequence is null");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
|
||||
["http://localhost:7071"],
|
||||
CHAIN_ID_NEAR,
|
||||
s[1],
|
||||
s[0].toString(),
|
||||
getEmitterAddressNear(token_bridge),
|
||||
sequence,
|
||||
{
|
||||
transport: NodeHttpTransport(),
|
||||
}
|
||||
|
@ -944,9 +971,15 @@ async function testNearSDK() {
|
|||
}
|
||||
|
||||
console.log("redeeming USDC on Near");
|
||||
console.log(
|
||||
await redeemOnNear(user2Account, token_bridge, transferAlgoToNearUSDC)
|
||||
let redeemMsgs = await redeemOnNear(
|
||||
provider,
|
||||
user2Account.accountId,
|
||||
token_bridge,
|
||||
transferAlgoToNearUSDC
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
|
||||
console.log(
|
||||
"YYY redeeming Rando on Near: " + uint8ArrayToHex(transferAlgoToNearRando)
|
||||
|
@ -964,9 +997,15 @@ async function testNearSDK() {
|
|||
})
|
||||
);
|
||||
|
||||
console.log(
|
||||
await redeemOnNear(user2Account, token_bridge, transferAlgoToNearRando)
|
||||
redeemMsgs = await redeemOnNear(
|
||||
provider,
|
||||
user2Account.accountId,
|
||||
token_bridge,
|
||||
transferAlgoToNearRando
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
|
||||
console.log(
|
||||
await userAccount.viewFunction(randoToken, "ft_balance_of", {
|
||||
|
@ -981,9 +1020,16 @@ async function testNearSDK() {
|
|||
);
|
||||
|
||||
console.log("redeeming NEAR on Near");
|
||||
console.log(
|
||||
await redeemOnNear(user2Account, token_bridge, transferAlgoToNearNEAR)
|
||||
|
||||
redeemMsgs = await redeemOnNear(
|
||||
provider,
|
||||
user2Account.accountId,
|
||||
token_bridge,
|
||||
transferAlgoToNearNEAR
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
|
||||
let userAccount2Address = nearProviders.getTransactionLastResult(
|
||||
await userAccount.functionCall({
|
||||
|
@ -1032,7 +1078,12 @@ async function testNearSDK() {
|
|||
{
|
||||
console.log("redeeming P3 NEAR on Near");
|
||||
console.log(
|
||||
await redeemOnNear(user2Account, token_bridge, transferAlgoToNearP3)
|
||||
await redeemOnNear(
|
||||
provider,
|
||||
user2Account.accountId,
|
||||
token_bridge,
|
||||
transferAlgoToNearP3
|
||||
)
|
||||
);
|
||||
|
||||
console.log(
|
||||
|
@ -1071,9 +1122,15 @@ async function testNearSDK() {
|
|||
}
|
||||
|
||||
console.log("YYY redeeming P3 random on Near");
|
||||
console.log(
|
||||
await redeemOnNear(user2Account, token_bridge, transferAlgoToNearRandoP3)
|
||||
const redeemMsgs = await redeemOnNear(
|
||||
provider,
|
||||
user2Account.accountId,
|
||||
token_bridge,
|
||||
transferAlgoToNearRandoP3
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await user2Account.functionCall(msg);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
|
|
|
@ -22,8 +22,10 @@ import {
|
|||
CHAIN_ID_NEAR,
|
||||
CONTRACTS,
|
||||
getEmitterAddressEth,
|
||||
getEmitterAddressNear,
|
||||
getSignedVAAWithRetry,
|
||||
hexToUint8Array,
|
||||
parseSequenceFromLogNear,
|
||||
transferTokenFromNear,
|
||||
uint8ArrayToHex,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
|
@ -85,9 +87,7 @@ async function transferTest() {
|
|||
// connect to near...
|
||||
let near = await nearConnect({
|
||||
headers: {},
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: networkId as string,
|
||||
nodeUrl: nearNodeUrl as string,
|
||||
});
|
||||
|
@ -120,9 +120,11 @@ async function transferTest() {
|
|||
near.connection,
|
||||
process.env.NEAR_ACCOUNT as string
|
||||
);
|
||||
const provider = userAccount.connection.provider;
|
||||
|
||||
let [sequence, emitterAddress] = await transferTokenFromNear(
|
||||
userAccount,
|
||||
const transferMsgs = await transferTokenFromNear(
|
||||
provider,
|
||||
userAccount.accountId,
|
||||
CONTRACTS.MAINNET.near.core,
|
||||
CONTRACTS.MAINNET.near.token_bridge,
|
||||
NEAR_TOKEN_ADDRESS,
|
||||
|
@ -131,12 +133,19 @@ async function transferTest() {
|
|||
CHAIN_ID_ETH,
|
||||
BigInt(0)
|
||||
);
|
||||
|
||||
if (sequence === -1) {
|
||||
let transferOutcome;
|
||||
for (const msg of transferMsgs) {
|
||||
transferOutcome = await userAccount.functionCall(msg);
|
||||
}
|
||||
const sequence = parseSequenceFromLogNear(transferOutcome);
|
||||
if (sequence === null) {
|
||||
console.log("No sequence found, check above for error");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const emitterAddress = getEmitterAddressNear(
|
||||
CONTRACTS.MAINNET.near.token_bridge
|
||||
);
|
||||
console.log("emitterAddress:", emitterAddress, "sequence:", sequence);
|
||||
|
||||
console.log(
|
||||
|
|
|
@ -133,9 +133,7 @@ async function transferTest() {
|
|||
// connect to near...
|
||||
let near = await nearConnect({
|
||||
headers: {},
|
||||
deps: {
|
||||
keyStore,
|
||||
},
|
||||
keyStore,
|
||||
networkId: networkId as string,
|
||||
nodeUrl: nearNodeUrl as string,
|
||||
});
|
||||
|
@ -292,11 +290,15 @@ async function transferTest() {
|
|||
console.log("VAA received!");
|
||||
console.log(uint8ArrayToHex(signedVAA));
|
||||
|
||||
await redeemOnNear(
|
||||
userAccount,
|
||||
const redeemMsgs = await redeemOnNear(
|
||||
userAccount.connection.provider,
|
||||
userAccount.accountId,
|
||||
CONTRACTS.MAINNET.near.token_bridge,
|
||||
signedVAA
|
||||
);
|
||||
for (const msg of redeemMsgs) {
|
||||
await userAccount.functionCall(msg);
|
||||
}
|
||||
|
||||
console.log("Redeemed!");
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"axios": "^0.24.0",
|
||||
"bech32": "^2.0.0",
|
||||
"js-base64": "^3.6.1",
|
||||
"near-api-js": "^0.45.1"
|
||||
"near-api-js": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
||||
|
@ -10097,11 +10097,11 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/near-api-js": {
|
||||
"version": "0.45.1",
|
||||
"resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-0.45.1.tgz",
|
||||
"integrity": "sha512-QyPO/vjvMFlcMO1DCpsqzmnSqPIyHsjK1Qi4B5ZR1cJCIWMkqugDF/TDf8FVQ85pmlcYeYwfiTqKanKz+3IG0A==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-1.0.0.tgz",
|
||||
"integrity": "sha512-OYItaQIYlKK27FG5PrqqtkTI8Vv9TEOCi7gXePYigS4o6WofXciAXNjr4sihDJ8Vzi6s7+eEkf3zTNP3042FBw==",
|
||||
"dependencies": {
|
||||
"bn.js": "5.2.0",
|
||||
"bn.js": "5.2.1",
|
||||
"borsh": "^0.7.0",
|
||||
"bs58": "^4.0.0",
|
||||
"depd": "^2.0.0",
|
||||
|
@ -10114,11 +10114,6 @@
|
|||
"tweetnacl": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/near-api-js/node_modules/bn.js": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
|
||||
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
|
||||
},
|
||||
"node_modules/near-api-js/node_modules/borsh": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz",
|
||||
|
@ -21156,11 +21151,11 @@
|
|||
"dev": true
|
||||
},
|
||||
"near-api-js": {
|
||||
"version": "0.45.1",
|
||||
"resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-0.45.1.tgz",
|
||||
"integrity": "sha512-QyPO/vjvMFlcMO1DCpsqzmnSqPIyHsjK1Qi4B5ZR1cJCIWMkqugDF/TDf8FVQ85pmlcYeYwfiTqKanKz+3IG0A==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-1.0.0.tgz",
|
||||
"integrity": "sha512-OYItaQIYlKK27FG5PrqqtkTI8Vv9TEOCi7gXePYigS4o6WofXciAXNjr4sihDJ8Vzi6s7+eEkf3zTNP3042FBw==",
|
||||
"requires": {
|
||||
"bn.js": "5.2.0",
|
||||
"bn.js": "5.2.1",
|
||||
"borsh": "^0.7.0",
|
||||
"bs58": "^4.0.0",
|
||||
"depd": "^2.0.0",
|
||||
|
@ -21173,11 +21168,6 @@
|
|||
"tweetnacl": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bn.js": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
|
||||
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
|
||||
},
|
||||
"borsh": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz",
|
||||
|
|
|
@ -68,6 +68,6 @@
|
|||
"axios": "^0.24.0",
|
||||
"bech32": "^2.0.0",
|
||||
"js-base64": "^3.6.1",
|
||||
"near-api-js": "^0.45.1"
|
||||
"near-api-js": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import { PublicKey } from "@solana/web3.js";
|
||||
import { decodeAddress, getApplicationAddress } from "algosdk";
|
||||
import { bech32 } from "bech32";
|
||||
import { arrayify, BytesLike, Hexable, zeroPad } from "ethers/lib/utils";
|
||||
import {
|
||||
arrayify,
|
||||
sha256,
|
||||
BytesLike,
|
||||
Hexable,
|
||||
zeroPad,
|
||||
} from "ethers/lib/utils";
|
||||
import { importTokenWasm } from "../solana/wasm";
|
||||
import { uint8ArrayToHex } from "../utils";
|
||||
import { sha256 } from "js-sha256";
|
||||
|
||||
export function getEmitterAddressEth(
|
||||
contractAddress: number | BytesLike | Hexable
|
||||
|
@ -35,5 +40,5 @@ export function getEmitterAddressAlgorand(appId: bigint): string {
|
|||
}
|
||||
|
||||
export function getEmitterAddressNear(programAddress: string): string {
|
||||
return sha256.hex(programAddress);
|
||||
return uint8ArrayToHex(arrayify(sha256(Buffer.from(programAddress, "utf8"))));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { TransactionResponse } from "@solana/web3.js";
|
||||
import { TxInfo } from "@terra-money/terra.js";
|
||||
import { BigNumber, ContractReceipt } from "ethers";
|
||||
import { FinalExecutionOutcome } from "near-api-js/lib/providers";
|
||||
import { Implementation__factory } from "../ethers-contracts";
|
||||
|
||||
export function parseSequenceFromLogEth(
|
||||
|
@ -123,17 +124,20 @@ export function parseSequenceFromLogAlgorand(
|
|||
return sequence;
|
||||
}
|
||||
|
||||
export function parseSequenceFromLogNear(result: any): [number, string] {
|
||||
let sequence = "";
|
||||
for (const o of result.receipts_outcome) {
|
||||
const NEAR_EVENT_PREFIX = "EVENT_JSON:";
|
||||
|
||||
export function parseSequenceFromLogNear(
|
||||
outcome: FinalExecutionOutcome
|
||||
): string | null {
|
||||
for (const o of outcome.receipts_outcome) {
|
||||
for (const l of o.outcome.logs) {
|
||||
if (l.startsWith("EVENT_JSON:")) {
|
||||
const body = JSON.parse(l.slice(11));
|
||||
if (l.startsWith(NEAR_EVENT_PREFIX)) {
|
||||
const body = JSON.parse(l.slice(NEAR_EVENT_PREFIX.length));
|
||||
if (body.standard === "wormhole" && body.event === "publish") {
|
||||
return [body.seq, body.emitter];
|
||||
return body.seq.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [-1, ""];
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ export async function getIsTransferCompletedTerra(
|
|||
gasPrices,
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
// redeemed if the VAA was already executed
|
||||
return e.response.data.message.includes("VaaAlreadyExecuted");
|
||||
}
|
||||
|
|
|
@ -83,6 +83,8 @@ export const TERRA_HOST =
|
|||
isClassic: true,
|
||||
};
|
||||
|
||||
export const NEAR_NODE_URL = ci ? "http://near:3030" : "http://localhost:3030";
|
||||
|
||||
describe("consts should exist", () => {
|
||||
it("has Solana test token", () => {
|
||||
expect.assertions(1);
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
import { beforeAll, afterAll, expect, jest, test } from "@jest/globals";
|
||||
import { ethers } from "ethers";
|
||||
import { parseUnits } from "ethers/lib/utils";
|
||||
import {
|
||||
createWrappedOnEth,
|
||||
createWrappedOnNear,
|
||||
getEmitterAddressEth,
|
||||
getEmitterAddressNear,
|
||||
getIsTransferCompletedEth,
|
||||
getIsTransferCompletedNear,
|
||||
hashAccount,
|
||||
hexToUint8Array,
|
||||
parseSequenceFromLogEth,
|
||||
parseSequenceFromLogNear,
|
||||
redeemOnEth,
|
||||
redeemOnNear,
|
||||
registerAccount,
|
||||
setDefaultWasm,
|
||||
tryNativeToUint8Array,
|
||||
updateWrappedOnEth,
|
||||
} from "../..";
|
||||
import { CHAIN_ID_ETH, CHAIN_ID_NEAR, CONTRACTS } from "../../utils/consts";
|
||||
import { attestFromEth, attestNearFromNear } from "../attest";
|
||||
import { approveEth, transferFromEth, transferNearFromNear } from "../transfer";
|
||||
import {
|
||||
ETH_NODE_URL,
|
||||
ETH_PRIVATE_KEY5,
|
||||
NEAR_NODE_URL,
|
||||
TEST_ERC20,
|
||||
} from "./consts";
|
||||
import { getSignedVAABySequence } from "./helpers";
|
||||
import { Account, connect, KeyPair, keyStores, Near } from "near-api-js";
|
||||
import {
|
||||
FinalExecutionOutcome,
|
||||
getTransactionLastResult,
|
||||
Provider,
|
||||
} from "near-api-js/lib/providers";
|
||||
import { parseNearAmount } from "near-api-js/lib/utils/format";
|
||||
|
||||
setDefaultWasm("node");
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
let near: Near;
|
||||
let nearProvider: Provider;
|
||||
let account: Account;
|
||||
const networkId = "sandbox";
|
||||
const accountId = "devnet.test.near";
|
||||
const PRIVATE_KEY =
|
||||
"ed25519:nCW2EsTn91b7ettRqQX6ti8ZBNwo7tbMsenBu9nmSVG9aDhNB7hgw7S9w5M9CZu1bF23FbvhKZPfDmh2Gbs45Fs";
|
||||
|
||||
const ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
|
||||
const signer = new ethers.Wallet(ETH_PRIVATE_KEY5, ethProvider);
|
||||
const ethEmitterAddress = getEmitterAddressEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge
|
||||
);
|
||||
const nearEmitterAddress = getEmitterAddressNear(
|
||||
CONTRACTS.DEVNET.near.token_bridge
|
||||
);
|
||||
const ethTransferAmount = parseUnits("1", 18);
|
||||
let ethWalletAddress: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const keyStore = new keyStores.InMemoryKeyStore();
|
||||
await keyStore.setKey(networkId, accountId, KeyPair.fromString(PRIVATE_KEY));
|
||||
const config = {
|
||||
keyStore,
|
||||
networkId,
|
||||
nodeUrl: NEAR_NODE_URL,
|
||||
headers: {},
|
||||
};
|
||||
near = await connect(config);
|
||||
nearProvider = near.connection.provider;
|
||||
account = await near.account(accountId);
|
||||
ethWalletAddress = await signer.getAddress();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
ethProvider.destroy();
|
||||
});
|
||||
|
||||
const nearParseLogAndGetSignedVaa = async (outcome: FinalExecutionOutcome) => {
|
||||
const sequence = parseSequenceFromLogNear(outcome);
|
||||
if (sequence === null) {
|
||||
throw new Error("sequence is null");
|
||||
}
|
||||
return await getSignedVAABySequence(
|
||||
CHAIN_ID_NEAR,
|
||||
sequence,
|
||||
nearEmitterAddress
|
||||
);
|
||||
};
|
||||
|
||||
const ethParseLogAndGetSignedVaa = async (receipt: ethers.ContractReceipt) => {
|
||||
const sequence = parseSequenceFromLogEth(
|
||||
receipt,
|
||||
CONTRACTS.DEVNET.ethereum.core
|
||||
);
|
||||
return await getSignedVAABySequence(
|
||||
CHAIN_ID_ETH,
|
||||
sequence,
|
||||
ethEmitterAddress
|
||||
);
|
||||
};
|
||||
|
||||
test("Attest and transfer Near token from Near to Ethereum", async () => {
|
||||
// Attest
|
||||
const attestMsg = await attestNearFromNear(
|
||||
account.connection.provider,
|
||||
CONTRACTS.DEVNET.near.core,
|
||||
CONTRACTS.DEVNET.near.token_bridge
|
||||
);
|
||||
const attestOutcome = await account.functionCall(attestMsg);
|
||||
const attestSignedVaa = await nearParseLogAndGetSignedVaa(attestOutcome);
|
||||
try {
|
||||
await createWrappedOnEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
signer,
|
||||
attestSignedVaa
|
||||
);
|
||||
} catch {
|
||||
await updateWrappedOnEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
signer,
|
||||
attestSignedVaa
|
||||
);
|
||||
}
|
||||
// Transfer
|
||||
const transferMsg = await transferNearFromNear(
|
||||
account.connection.provider,
|
||||
CONTRACTS.DEVNET.near.core,
|
||||
CONTRACTS.DEVNET.near.token_bridge,
|
||||
BigInt(parseNearAmount("1") || ""),
|
||||
tryNativeToUint8Array(ethWalletAddress, "ethereum"),
|
||||
"ethereum",
|
||||
BigInt(0)
|
||||
);
|
||||
const transferOutcome = await account.functionCall(transferMsg);
|
||||
const transferSignedVAA = await nearParseLogAndGetSignedVaa(transferOutcome);
|
||||
await redeemOnEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
signer,
|
||||
transferSignedVAA
|
||||
);
|
||||
expect(
|
||||
await getIsTransferCompletedEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
ethProvider,
|
||||
transferSignedVAA
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("Attest and transfer token from Ethereum to Near", async () => {
|
||||
// Attest
|
||||
const attestReceipt = await attestFromEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
signer,
|
||||
TEST_ERC20
|
||||
);
|
||||
const attestSignedVaa = await ethParseLogAndGetSignedVaa(attestReceipt);
|
||||
const createWrappedMsgs = await createWrappedOnNear(
|
||||
nearProvider,
|
||||
CONTRACTS.DEVNET.near.token_bridge,
|
||||
attestSignedVaa
|
||||
);
|
||||
for (const msg of createWrappedMsgs) {
|
||||
await account.functionCall(msg);
|
||||
}
|
||||
// Transfer
|
||||
await approveEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
TEST_ERC20,
|
||||
signer,
|
||||
ethTransferAmount
|
||||
);
|
||||
let { isRegistered, accountHash } = await hashAccount(
|
||||
nearProvider,
|
||||
CONTRACTS.DEVNET.near.token_bridge,
|
||||
account.accountId
|
||||
);
|
||||
if (!isRegistered) {
|
||||
const registerAccountMsg = registerAccount(
|
||||
account.accountId,
|
||||
CONTRACTS.DEVNET.near.token_bridge
|
||||
);
|
||||
accountHash = getTransactionLastResult(
|
||||
await account.functionCall(registerAccountMsg)
|
||||
);
|
||||
}
|
||||
const transferReceipt = await transferFromEth(
|
||||
CONTRACTS.DEVNET.ethereum.token_bridge,
|
||||
signer,
|
||||
TEST_ERC20,
|
||||
ethTransferAmount,
|
||||
"near",
|
||||
hexToUint8Array(accountHash)
|
||||
);
|
||||
const transferSignedVaa = await ethParseLogAndGetSignedVaa(transferReceipt);
|
||||
const redeemMsgs = await redeemOnNear(
|
||||
nearProvider,
|
||||
account.accountId,
|
||||
CONTRACTS.DEVNET.near.token_bridge,
|
||||
transferSignedVaa
|
||||
);
|
||||
expect(
|
||||
await getIsTransferCompletedNear(
|
||||
nearProvider,
|
||||
CONTRACTS.DEVNET.near.token_bridge,
|
||||
transferSignedVaa
|
||||
)
|
||||
).toBe(false);
|
||||
for (const msg of redeemMsgs) {
|
||||
await account.functionCall(msg);
|
||||
}
|
||||
expect(
|
||||
await getIsTransferCompletedNear(
|
||||
nearProvider,
|
||||
CONTRACTS.DEVNET.near.token_bridge,
|
||||
transferSignedVaa
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
|
@ -11,21 +11,26 @@ import {
|
|||
OnApplicationComplete,
|
||||
SuggestedParams,
|
||||
} from "algosdk";
|
||||
import { Account as nearAccount } from "near-api-js";
|
||||
const BN = require("bn.js");
|
||||
import BN from "bn.js";
|
||||
import { ethers, PayableOverrides } from "ethers";
|
||||
import { isNativeDenom } from "..";
|
||||
import { getMessageFee, optin, TransactionSignerPair } from "../algorand";
|
||||
import { Bridge__factory } from "../ethers-contracts";
|
||||
import { getBridgeFeeIx, ixFromRust } from "../solana";
|
||||
import { importTokenWasm } from "../solana/wasm";
|
||||
import { textToHexString, textToUint8Array, uint8ArrayToHex } from "../utils";
|
||||
import {
|
||||
callFunctionNear,
|
||||
hashAccount,
|
||||
textToHexString,
|
||||
textToUint8Array,
|
||||
uint8ArrayToHex,
|
||||
} from "../utils";
|
||||
import { safeBigIntToNumber } from "../utils/bigint";
|
||||
import { createNonce } from "../utils/createNonce";
|
||||
import { parseSequenceFromLogNear } from "../bridge/parseSequenceFromLog";
|
||||
|
||||
import { getIsWrappedAssetNear } from ".";
|
||||
import { isNativeDenomInjective } from "../cosmwasm";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
import { FunctionCallOptions } from "near-api-js/lib/account";
|
||||
|
||||
export async function attestFromEth(
|
||||
tokenBridgeAddress: string,
|
||||
|
@ -240,37 +245,23 @@ export async function attestFromAlgorand(
|
|||
return txs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attest an already created asset
|
||||
* If you create a new asset on near and want to transfer it elsewhere,
|
||||
* you create an attestation for it on near... pass that vaa to the target chain..
|
||||
* submit it.. then you can transfer from near to that target chain
|
||||
* @param client An Near account client
|
||||
* @param coreBridge The account for the core bridge
|
||||
* @param tokenBridge The account for the token bridge
|
||||
* @param asset The account for the asset
|
||||
* @returns [sequenceNumber, emitter]
|
||||
*/
|
||||
export async function attestTokenFromNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
coreBridge: string,
|
||||
tokenBridge: string,
|
||||
asset: string
|
||||
): Promise<[number, string]> {
|
||||
let message_fee = await client.viewFunction(coreBridge, "message_fee", {});
|
||||
// Non-signing event
|
||||
): Promise<FunctionCallOptions[]> {
|
||||
const options: FunctionCallOptions[] = [];
|
||||
const messageFee = await callFunctionNear(
|
||||
provider,
|
||||
coreBridge,
|
||||
"message_fee"
|
||||
);
|
||||
if (!getIsWrappedAssetNear(tokenBridge, asset)) {
|
||||
// Non-signing event that hits the RPC
|
||||
let res = await client.viewFunction(tokenBridge, "hash_account", {
|
||||
account: asset,
|
||||
});
|
||||
|
||||
// if res[0] == false, the account has not been
|
||||
// registered... The first user to attest a non-wormhole token
|
||||
// is gonna have to pay for the space
|
||||
if (!res[0]) {
|
||||
// Signing event
|
||||
await client.functionCall({
|
||||
const { isRegistered } = await hashAccount(provider, tokenBridge, asset);
|
||||
if (!isRegistered) {
|
||||
// The account has not been registered. The first user to attest a non-wormhole token pays for the space
|
||||
options.push({
|
||||
contractId: tokenBridge,
|
||||
methodName: "register_account",
|
||||
args: { account: asset },
|
||||
|
@ -279,41 +270,28 @@ export async function attestTokenFromNear(
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Signing event
|
||||
let result = await client.functionCall({
|
||||
options.push({
|
||||
contractId: tokenBridge,
|
||||
methodName: "attest_token",
|
||||
args: { token: asset, message_fee: message_fee },
|
||||
attachedDeposit: new BN("3000000000000000000000").add(new BN(message_fee)), // 0.003 NEAR
|
||||
args: { token: asset, message_fee: messageFee },
|
||||
attachedDeposit: new BN("3000000000000000000000").add(new BN(messageFee)), // 0.003 NEAR
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
|
||||
return parseSequenceFromLogNear(result);
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attest NEAR
|
||||
* @param client An Near account client
|
||||
* @param coreBridge The account for the core bridge
|
||||
* @param tokenBridge The account for the token bridge
|
||||
* @returns [sequenceNumber, emitter]
|
||||
*/
|
||||
export async function attestNearFromNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
coreBridge: string,
|
||||
tokenBridge: string
|
||||
): Promise<[number, string]> {
|
||||
let message_fee =
|
||||
(await client.viewFunction(coreBridge, "message_fee", {})) + 1;
|
||||
|
||||
let result = await client.functionCall({
|
||||
): Promise<FunctionCallOptions> {
|
||||
const messageFee =
|
||||
(await callFunctionNear(provider, coreBridge, "message_fee")) + 1;
|
||||
return {
|
||||
contractId: tokenBridge,
|
||||
methodName: "attest_near",
|
||||
args: { message_fee: message_fee },
|
||||
attachedDeposit: new BN(message_fee),
|
||||
args: { message_fee: messageFee },
|
||||
attachedDeposit: new BN(messageFee),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
|
||||
return parseSequenceFromLogNear(result);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,11 +8,10 @@ import { Bridge__factory } from "../ethers-contracts";
|
|||
import { ixFromRust } from "../solana";
|
||||
import { importTokenWasm } from "../solana/wasm";
|
||||
import { submitVAAOnInjective } from "./redeem";
|
||||
import {
|
||||
Account as nearAccount,
|
||||
providers as nearProviders,
|
||||
} from "near-api-js";
|
||||
import BN from "bn.js";
|
||||
import { FunctionCallOptions } from "near-api-js/lib/account";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
import { callFunctionNear } from "../utils";
|
||||
|
||||
export async function createWrappedOnEth(
|
||||
tokenBridgeAddress: string,
|
||||
|
@ -80,30 +79,25 @@ export async function createWrappedOnAlgorand(
|
|||
}
|
||||
|
||||
export async function createWrappedOnNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
tokenBridge: string,
|
||||
attestVAA: Uint8Array
|
||||
): Promise<string> {
|
||||
// Could we just pass in the vaa already as hex?
|
||||
let vaa = Buffer.from(attestVAA).toString("hex");
|
||||
|
||||
let res = await client.viewFunction(tokenBridge, "deposit_estimates", {});
|
||||
|
||||
let result = await client.functionCall({
|
||||
contractId: tokenBridge,
|
||||
methodName: "submit_vaa",
|
||||
args: { vaa: vaa },
|
||||
attachedDeposit: new BN(res[1]),
|
||||
gas: new BN("150000000000000"),
|
||||
});
|
||||
|
||||
result = await client.functionCall({
|
||||
contractId: tokenBridge,
|
||||
methodName: "submit_vaa",
|
||||
args: { vaa: vaa },
|
||||
attachedDeposit: new BN(res[1]),
|
||||
gas: new BN("150000000000000"),
|
||||
});
|
||||
|
||||
return nearProviders.getTransactionLastResult(result);
|
||||
): Promise<FunctionCallOptions[]> {
|
||||
const vaa = Buffer.from(attestVAA).toString("hex");
|
||||
const res = await callFunctionNear(
|
||||
provider,
|
||||
tokenBridge,
|
||||
"deposit_estimates"
|
||||
);
|
||||
const msgs = [
|
||||
{
|
||||
contractId: tokenBridge,
|
||||
methodName: "submit_vaa",
|
||||
args: { vaa },
|
||||
attachedDeposit: new BN(res[1]),
|
||||
gas: new BN("150000000000000"),
|
||||
},
|
||||
];
|
||||
msgs.push({ ...msgs[0] });
|
||||
return msgs;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
import { LCDClient } from "@terra-money/terra.js";
|
||||
import { ChainGrpcWasmApi } from "@injectivelabs/sdk-ts";
|
||||
import { getNetworkInfo, Network } from "@injectivelabs/networks";
|
||||
import { Algodv2 } from "algosdk";
|
||||
import { ethers } from "ethers";
|
||||
import { fromUint8Array } from "js-base64";
|
||||
|
@ -13,13 +12,13 @@ import {
|
|||
import { Bridge__factory } from "../ethers-contracts";
|
||||
import { importTokenWasm } from "../solana/wasm";
|
||||
import {
|
||||
callFunctionNear,
|
||||
ChainId,
|
||||
ChainName,
|
||||
CHAIN_ID_ALGORAND,
|
||||
coalesceChainId,
|
||||
} from "../utils";
|
||||
import { Account as nearAccount } from "near-api-js";
|
||||
const BN = require("bn.js");
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
|
||||
/**
|
||||
* Returns a foreign asset address on Ethereum for a provided native chain and asset address, AddressZero if it does not exist
|
||||
|
@ -165,17 +164,19 @@ export async function getForeignAssetAlgorand(
|
|||
}
|
||||
|
||||
export async function getForeignAssetNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
tokenAccount: string,
|
||||
chain: ChainId | ChainName,
|
||||
contract: string
|
||||
): Promise<string | null> {
|
||||
const chainId = coalesceChainId(chain);
|
||||
|
||||
let ret = await client.viewFunction(tokenAccount, "get_foreign_asset", {
|
||||
chain: chainId,
|
||||
address: contract,
|
||||
});
|
||||
if (ret === "") return null;
|
||||
else return ret;
|
||||
const ret = await callFunctionNear(
|
||||
provider,
|
||||
tokenAccount,
|
||||
"get_foreign_asset",
|
||||
{
|
||||
chain: coalesceChainId(chain),
|
||||
address: contract,
|
||||
}
|
||||
);
|
||||
return ret !== "" ? ret : null;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import { ChainGrpcWasmApi } from "@injectivelabs/sdk-ts";
|
|||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
import { LCDClient } from "@terra-money/terra.js";
|
||||
import { Algodv2, bigIntToBytes } from "algosdk";
|
||||
import { Account as nearAccount } from "near-api-js";
|
||||
import axios from "axios";
|
||||
import { ethers } from "ethers";
|
||||
import { fromUint8Array } from "js-base64";
|
||||
|
@ -14,10 +13,12 @@ import {
|
|||
MAX_BITS,
|
||||
_parseVAAAlgorand,
|
||||
} from "../algorand";
|
||||
import { callFunctionNear } from "../utils/near";
|
||||
import { getSignedVAAHash } from "../bridge";
|
||||
import { Bridge__factory } from "../ethers-contracts";
|
||||
import { importCoreWasm } from "../solana/wasm";
|
||||
import { safeBigIntToNumber } from "../utils/bigint";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
|
||||
export async function getIsTransferCompletedEth(
|
||||
tokenBridgeAddress: string,
|
||||
|
@ -220,24 +221,15 @@ export async function getIsTransferCompletedAlgorand(
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns true if this transfer was completed on Near</p>
|
||||
* @param near account
|
||||
* @param tokenAccount the Token bridge account
|
||||
* @param signedVAA VAA to check
|
||||
* @returns true if VAA has been redeemed, false otherwise
|
||||
*/
|
||||
export async function getIsTransferCompletedNear(
|
||||
client: nearAccount,
|
||||
tokenAccount: string,
|
||||
provider: Provider,
|
||||
tokenBridge: string,
|
||||
signedVAA: Uint8Array
|
||||
): Promise<boolean> {
|
||||
// Could we just pass in the vaa already as hex?
|
||||
let vaa = Buffer.from(signedVAA).toString("hex");
|
||||
|
||||
const vaa = Buffer.from(signedVAA).toString("hex");
|
||||
return (
|
||||
await client.viewFunction(tokenAccount, "is_transfer_completed", {
|
||||
vaa: vaa,
|
||||
await callFunctionNear(provider, tokenBridge, "is_transfer_completed", {
|
||||
vaa,
|
||||
})
|
||||
)[1];
|
||||
}
|
||||
|
|
|
@ -108,12 +108,6 @@ export async function getIsWrappedAssetAlgorand(
|
|||
return wormhole;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whethor or not an asset on Near is a wormhole wrapped asset
|
||||
* @param tokenBridge token bridge account
|
||||
* @param asset Near asset account
|
||||
* @returns true if the asset is wrapped
|
||||
*/
|
||||
export function getIsWrappedAssetNear(
|
||||
tokenBridge: string,
|
||||
asset: string
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
const sha256 = require("js-sha256");
|
||||
|
||||
import { getNetworkInfo, Network } from "@injectivelabs/networks";
|
||||
import { ChainGrpcWasmApi } from "@injectivelabs/sdk-ts";
|
||||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
import { LCDClient } from "@terra-money/terra.js";
|
||||
import { Algodv2 } from "algosdk";
|
||||
import { ethers } from "ethers";
|
||||
import { arrayify, zeroPad } from "ethers/lib/utils";
|
||||
import { arrayify, sha256, zeroPad } from "ethers/lib/utils";
|
||||
import { decodeLocalState } from "../algorand";
|
||||
import { buildTokenId, isNativeCosmWasmDenom } from "../cosmwasm/address";
|
||||
import { TokenImplementation__factory } from "../ethers-contracts";
|
||||
import { importTokenWasm } from "../solana/wasm";
|
||||
import { buildNativeId, isNativeDenom } from "../terra";
|
||||
import { buildNativeId } from "../terra";
|
||||
import { canonicalAddress } from "../cosmos";
|
||||
import {
|
||||
ChainId,
|
||||
|
@ -27,6 +24,7 @@ import {
|
|||
hexToUint8Array,
|
||||
coalesceCosmWasmChainId,
|
||||
tryHexToNativeAssetString,
|
||||
callFunctionNear,
|
||||
} from "../utils";
|
||||
import { safeBigIntToNumber } from "../utils/bigint";
|
||||
import {
|
||||
|
@ -34,7 +32,7 @@ import {
|
|||
getIsWrappedAssetEth,
|
||||
getIsWrappedAssetNear,
|
||||
} from "./getIsWrappedAsset";
|
||||
import { Account as nearAccount } from "near-api-js";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
|
||||
// TODO: remove `as ChainId` and return number in next minor version as we can't ensure it will match our type definition
|
||||
export interface WormholeWrappedInfo {
|
||||
|
@ -269,26 +267,31 @@ export async function getOriginalAssetAlgorand(
|
|||
}
|
||||
|
||||
export async function getOriginalAssetNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
tokenAccount: string,
|
||||
assetAccount: string
|
||||
): Promise<WormholeWrappedInfo> {
|
||||
let retVal: WormholeWrappedInfo = {
|
||||
const retVal: WormholeWrappedInfo = {
|
||||
isWrapped: false,
|
||||
chainId: CHAIN_ID_NEAR,
|
||||
assetAddress: new Uint8Array(),
|
||||
};
|
||||
retVal.isWrapped = await getIsWrappedAssetNear(tokenAccount, assetAccount);
|
||||
if (!retVal.isWrapped) {
|
||||
retVal.assetAddress = sha256.sha256.hex(
|
||||
Buffer.from(assetAccount).toString("hex")
|
||||
);
|
||||
retVal.assetAddress = assetAccount
|
||||
? arrayify(sha256(Buffer.from(assetAccount)))
|
||||
: zeroPad(arrayify("0x"), 32);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
let buf = await client.viewFunction(tokenAccount, "get_original_asset", {
|
||||
token: assetAccount,
|
||||
});
|
||||
const buf = await callFunctionNear(
|
||||
provider,
|
||||
tokenAccount,
|
||||
"get_original_asset",
|
||||
{
|
||||
token: assetAccount,
|
||||
}
|
||||
);
|
||||
|
||||
retVal.chainId = buf[1];
|
||||
retVal.assetAddress = hexToUint8Array(buf[0]);
|
||||
|
|
|
@ -18,11 +18,12 @@ import {
|
|||
CHAIN_ID_NEAR,
|
||||
CHAIN_ID_SOLANA,
|
||||
ChainId,
|
||||
ChainName,
|
||||
MAX_VAA_DECIMALS,
|
||||
WSOL_ADDRESS,
|
||||
WSOL_DECIMALS,
|
||||
uint8ArrayToHex,
|
||||
callFunctionNear,
|
||||
hashLookup,
|
||||
} from "../utils";
|
||||
|
||||
import { getForeignAssetNear } from ".";
|
||||
|
@ -31,10 +32,10 @@ import { _parseVAAAlgorand } from "../algorand";
|
|||
|
||||
import { hexToNativeString } from "../utils/array";
|
||||
import { parseTransferPayload } from "../utils/parseVaa";
|
||||
import { Account as nearAccount } from "near-api-js";
|
||||
import BN from "bn.js";
|
||||
import { providers as nearProviders } from "near-api-js";
|
||||
import { MsgExecuteContract as MsgExecuteContractInjective } from "@injectivelabs/sdk-ts";
|
||||
import { FunctionCallOptions } from "near-api-js/lib/account";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
|
||||
export async function redeemOnEth(
|
||||
tokenBridgeAddress: string,
|
||||
|
@ -256,66 +257,63 @@ export async function redeemOnAlgorand(
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This basically just submits the VAA to Near
|
||||
* @param client
|
||||
* @param tokenBridge Token bridge ID
|
||||
* @param vaa The VAA to be redeemed
|
||||
* @returns Transaction ID(s)
|
||||
*/
|
||||
export async function redeemOnNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
account: string,
|
||||
tokenBridge: string,
|
||||
vaa: Uint8Array
|
||||
): Promise<String> {
|
||||
let p = _parseVAAAlgorand(vaa);
|
||||
): Promise<FunctionCallOptions[]> {
|
||||
const options: FunctionCallOptions[] = [];
|
||||
const p = _parseVAAAlgorand(vaa);
|
||||
|
||||
if (p.ToChain !== CHAIN_ID_NEAR) {
|
||||
throw new Error("Not destined for NEAR");
|
||||
}
|
||||
|
||||
let user = await client.viewFunction(tokenBridge, "hash_lookup", {
|
||||
hash: uint8ArrayToHex(p.ToAddress as Uint8Array),
|
||||
});
|
||||
const { found, value: receiver } = await hashLookup(
|
||||
provider,
|
||||
tokenBridge,
|
||||
uint8ArrayToHex(p.ToAddress as Uint8Array)
|
||||
);
|
||||
|
||||
if (!user[0]) {
|
||||
if (!found) {
|
||||
throw new Error(
|
||||
"Unregistered receiver (receiving account is not registered)"
|
||||
);
|
||||
}
|
||||
|
||||
user = user[1];
|
||||
|
||||
let token = await getForeignAssetNear(
|
||||
client,
|
||||
const token = await getForeignAssetNear(
|
||||
provider,
|
||||
tokenBridge,
|
||||
p.FromChain as ChainId,
|
||||
p.Contract as string
|
||||
);
|
||||
|
||||
if (token === "") {
|
||||
throw new Error("Unregistered token (this been attested yet?)");
|
||||
}
|
||||
|
||||
if (
|
||||
(p.Contract as string) !==
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
) {
|
||||
let bal = await client.viewFunction(token as string, "storage_balance_of", {
|
||||
account_id: user,
|
||||
});
|
||||
if (token === "" || token === null) {
|
||||
throw new Error("Unregistered token (has it been attested?)");
|
||||
}
|
||||
|
||||
const bal = await callFunctionNear(
|
||||
provider,
|
||||
token as string,
|
||||
"storage_balance_of",
|
||||
{
|
||||
account_id: receiver,
|
||||
}
|
||||
);
|
||||
|
||||
if (bal === null) {
|
||||
console.log("Registering ", user, " for ", token);
|
||||
bal = nearProviders.getTransactionLastResult(
|
||||
await client.functionCall({
|
||||
contractId: token as string,
|
||||
methodName: "storage_deposit",
|
||||
args: { account_id: user, registration_only: true },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"), // 0.002 NEAR
|
||||
})
|
||||
);
|
||||
options.push({
|
||||
contractId: token as string,
|
||||
methodName: "storage_deposit",
|
||||
args: { account_id: receiver, registration_only: true },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"), // 0.002 NEAR
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -328,30 +326,28 @@ export async function redeemOnNear(
|
|||
)
|
||||
) !== 0
|
||||
) {
|
||||
let bal = await client.viewFunction(
|
||||
const bal = await callFunctionNear(
|
||||
provider,
|
||||
token as string,
|
||||
"storage_balance_of",
|
||||
{
|
||||
account_id: client.accountId,
|
||||
account_id: account,
|
||||
}
|
||||
);
|
||||
|
||||
if (bal === null) {
|
||||
console.log("Registering ", client.accountId, " for ", token);
|
||||
bal = nearProviders.getTransactionLastResult(
|
||||
await client.functionCall({
|
||||
contractId: token as string,
|
||||
methodName: "storage_deposit",
|
||||
args: { account_id: client.accountId, registration_only: true },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"), // 0.002 NEAR
|
||||
})
|
||||
);
|
||||
options.push({
|
||||
contractId: token as string,
|
||||
methodName: "storage_deposit",
|
||||
args: { account_id: account, registration_only: true },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"), // 0.002 NEAR
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = await client.functionCall({
|
||||
options.push({
|
||||
contractId: tokenBridge,
|
||||
methodName: "submit_vaa",
|
||||
args: {
|
||||
|
@ -361,7 +357,7 @@ export async function redeemOnNear(
|
|||
gas: new BN("150000000000000"),
|
||||
});
|
||||
|
||||
result = await client.functionCall({
|
||||
options.push({
|
||||
contractId: tokenBridge,
|
||||
methodName: "submit_vaa",
|
||||
args: {
|
||||
|
@ -371,5 +367,5 @@ export async function redeemOnNear(
|
|||
gas: new BN("150000000000000"),
|
||||
});
|
||||
|
||||
return nearProviders.getTransactionLastResult(result);
|
||||
return options;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
Transaction as AlgorandTransaction,
|
||||
} from "algosdk";
|
||||
import { ethers, Overrides, PayableOverrides } from "ethers";
|
||||
import { isNativeDenom } from "..";
|
||||
import { getIsWrappedAssetNear, isNativeDenom } from "..";
|
||||
import {
|
||||
assetOptinCheck,
|
||||
getMessageFee,
|
||||
|
@ -44,16 +44,13 @@ import {
|
|||
textToUint8Array,
|
||||
uint8ArrayToHex,
|
||||
CHAIN_ID_SOLANA,
|
||||
callFunctionNear,
|
||||
} from "../utils";
|
||||
import { safeBigIntToNumber } from "../utils/bigint";
|
||||
import { isNativeDenomInjective } from "../cosmwasm";
|
||||
import {
|
||||
Account as nearAccount,
|
||||
providers as nearProviders,
|
||||
} from "near-api-js";
|
||||
import { parseSequenceFromLogNear } from "../bridge/parseSequenceFromLog";
|
||||
|
||||
const BN = require("bn.js");
|
||||
import { FunctionCallOptions } from "near-api-js/lib/account";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
|
||||
export async function getAllowanceEth(
|
||||
tokenBridgeAddress: string,
|
||||
|
@ -725,21 +722,9 @@ export async function transferFromAlgorand(
|
|||
return txs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers an asset from Near to a receiver on another chain
|
||||
* @param client
|
||||
* @param coreBridge account
|
||||
* @param tokenBridge account of the token bridge
|
||||
* @param assetId account
|
||||
* @param qty Quantity to transfer
|
||||
* @param receiver Receiving account
|
||||
* @param chain Reeiving chain
|
||||
* @param fee Transfer fee
|
||||
* @param payload payload for payload3 transfers
|
||||
* @returns [Sequence number of confirmation, emitter]
|
||||
*/
|
||||
export async function transferTokenFromNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
account: string,
|
||||
coreBridge: string,
|
||||
tokenBridge: string,
|
||||
assetId: string,
|
||||
|
@ -748,54 +733,70 @@ export async function transferTokenFromNear(
|
|||
chain: ChainId | ChainName,
|
||||
fee: bigint,
|
||||
payload: string = ""
|
||||
): Promise<[number, string]> {
|
||||
let wormhole = assetId.endsWith("." + tokenBridge);
|
||||
): Promise<FunctionCallOptions[]> {
|
||||
const isWrapped = getIsWrappedAssetNear(tokenBridge, assetId);
|
||||
|
||||
let result;
|
||||
const messageFee = await callFunctionNear(
|
||||
provider,
|
||||
coreBridge,
|
||||
"message_fee",
|
||||
{}
|
||||
);
|
||||
|
||||
let message_fee = await client.viewFunction(coreBridge, "message_fee", {});
|
||||
chain = coalesceChainId(chain);
|
||||
|
||||
if (wormhole) {
|
||||
result = await client.functionCall({
|
||||
contractId: tokenBridge,
|
||||
methodName: "send_transfer_wormhole_token",
|
||||
args: {
|
||||
token: assetId,
|
||||
amount: qty.toString(10),
|
||||
receiver: uint8ArrayToHex(receiver),
|
||||
chain: chain,
|
||||
fee: fee.toString(10),
|
||||
payload: payload,
|
||||
message_fee: message_fee,
|
||||
if (isWrapped) {
|
||||
return [
|
||||
{
|
||||
contractId: tokenBridge,
|
||||
methodName: "send_transfer_wormhole_token",
|
||||
args: {
|
||||
token: assetId,
|
||||
amount: qty.toString(10),
|
||||
receiver: uint8ArrayToHex(receiver),
|
||||
chain,
|
||||
fee: fee.toString(10),
|
||||
payload: payload,
|
||||
message_fee: messageFee,
|
||||
},
|
||||
attachedDeposit: new BN(messageFee + 1),
|
||||
gas: new BN("100000000000000"),
|
||||
},
|
||||
attachedDeposit: new BN(message_fee + 1),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
];
|
||||
} else {
|
||||
let bal = await client.viewFunction(assetId, "storage_balance_of", {
|
||||
account_id: tokenBridge,
|
||||
});
|
||||
const options: FunctionCallOptions[] = [];
|
||||
const bal = await callFunctionNear(
|
||||
provider,
|
||||
assetId,
|
||||
"storage_balance_of",
|
||||
{
|
||||
account_id: tokenBridge,
|
||||
}
|
||||
);
|
||||
if (bal === null) {
|
||||
// Looks like we have to stake some storage for this asset
|
||||
// for the token bridge...
|
||||
nearProviders.getTransactionLastResult(
|
||||
await client.functionCall({
|
||||
contractId: assetId,
|
||||
methodName: "storage_deposit",
|
||||
args: { account_id: tokenBridge, registration_only: true },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"), // 0.002 NEAR
|
||||
})
|
||||
);
|
||||
options.push({
|
||||
contractId: assetId,
|
||||
methodName: "storage_deposit",
|
||||
args: { account_id: tokenBridge, registration_only: true },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"), // 0.002 NEAR
|
||||
});
|
||||
}
|
||||
|
||||
if (message_fee > 0) {
|
||||
let bank = await client.viewFunction(tokenBridge, "bank_balance", {
|
||||
acct: client.accountId,
|
||||
});
|
||||
if (messageFee > 0) {
|
||||
const bank = await callFunctionNear(
|
||||
provider,
|
||||
tokenBridge,
|
||||
"bank_balance",
|
||||
{
|
||||
acct: account,
|
||||
}
|
||||
);
|
||||
|
||||
if (!bank[0]) {
|
||||
await client.functionCall({
|
||||
options.push({
|
||||
contractId: tokenBridge,
|
||||
methodName: "register_bank",
|
||||
args: {},
|
||||
|
@ -804,18 +805,18 @@ export async function transferTokenFromNear(
|
|||
});
|
||||
}
|
||||
|
||||
if (bank[1] < message_fee) {
|
||||
await client.functionCall({
|
||||
if (bank[1] < messageFee) {
|
||||
options.push({
|
||||
contractId: tokenBridge,
|
||||
methodName: "fill_bank",
|
||||
args: {},
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN(message_fee),
|
||||
attachedDeposit: new BN(messageFee),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result = await client.functionCall({
|
||||
options.push({
|
||||
contractId: assetId,
|
||||
methodName: "ft_transfer_call",
|
||||
args: {
|
||||
|
@ -823,34 +824,22 @@ export async function transferTokenFromNear(
|
|||
amount: qty.toString(10),
|
||||
msg: JSON.stringify({
|
||||
receiver: uint8ArrayToHex(receiver),
|
||||
chain: chain,
|
||||
chain,
|
||||
fee: fee.toString(10),
|
||||
payload: payload,
|
||||
message_fee: message_fee,
|
||||
message_fee: messageFee,
|
||||
}),
|
||||
},
|
||||
attachedDeposit: new BN(1),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
}
|
||||
|
||||
return parseSequenceFromLogNear(result);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers NEAR from Near to a receiver on another chain
|
||||
* @param client
|
||||
* @param coreBridge account
|
||||
* @param tokenBridge account of the token bridge
|
||||
* @param qty Quantity to transfer
|
||||
* @param receiver Receiving account
|
||||
* @param chain Reeiving chain
|
||||
* @param fee Transfer fee
|
||||
* @param payload payload for payload3 transfers
|
||||
* @returns [Sequence number of confirmation, emitter]
|
||||
*/
|
||||
export async function transferNearFromNear(
|
||||
client: nearAccount,
|
||||
provider: Provider,
|
||||
coreBridge: string,
|
||||
tokenBridge: string,
|
||||
qty: bigint,
|
||||
|
@ -858,22 +847,24 @@ export async function transferNearFromNear(
|
|||
chain: ChainId | ChainName,
|
||||
fee: bigint,
|
||||
payload: string = ""
|
||||
): Promise<[number, string]> {
|
||||
let message_fee = await client.viewFunction(coreBridge, "message_fee", {});
|
||||
|
||||
let result = await client.functionCall({
|
||||
): Promise<FunctionCallOptions> {
|
||||
const messageFee = await callFunctionNear(
|
||||
provider,
|
||||
coreBridge,
|
||||
"message_fee",
|
||||
{}
|
||||
);
|
||||
return {
|
||||
contractId: tokenBridge,
|
||||
methodName: "send_transfer_near",
|
||||
args: {
|
||||
receiver: uint8ArrayToHex(receiver),
|
||||
chain: chain,
|
||||
chain: coalesceChainId(chain),
|
||||
fee: fee.toString(10),
|
||||
payload: payload,
|
||||
message_fee: message_fee,
|
||||
message_fee: messageFee,
|
||||
},
|
||||
attachedDeposit: new BN(qty.toString(10)).add(new BN(message_fee)),
|
||||
attachedDeposit: new BN(qty.toString(10)).add(new BN(messageFee)),
|
||||
gas: new BN("100000000000000"),
|
||||
});
|
||||
|
||||
return parseSequenceFromLogNear(result);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { arrayify, zeroPad } from "@ethersproject/bytes";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { hexValue, hexZeroPad, stripZeros } from "ethers/lib/utils";
|
||||
import { hexValue, hexZeroPad, sha256, stripZeros } from "ethers/lib/utils";
|
||||
import { Provider as NearProvider } from "near-api-js/lib/providers";
|
||||
import {
|
||||
hexToNativeAssetStringAlgorand,
|
||||
nativeStringToHexAlgorand,
|
||||
|
@ -28,6 +29,7 @@ import {
|
|||
isTerraChain,
|
||||
CHAIN_ID_PYTHNET,
|
||||
} from "./consts";
|
||||
import { hashLookup } from "./near";
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -96,7 +98,7 @@ export const tryUint8ArrayToNative = (
|
|||
// wormhole-chain addresses are always 20 bytes.
|
||||
return humanAddress("wormhole", a.slice(-20));
|
||||
} else if (chainId === CHAIN_ID_NEAR) {
|
||||
throw Error("uint8ArrayToNative: Near not supported yet.");
|
||||
throw Error("uint8ArrayToNative: Use tryHexToNativeStringNear instead.");
|
||||
} else if (chainId === CHAIN_ID_OSMOSIS) {
|
||||
throw Error("uint8ArrayToNative: Osmosis not supported yet.");
|
||||
} else if (chainId === CHAIN_ID_SUI) {
|
||||
|
@ -112,6 +114,18 @@ export const tryUint8ArrayToNative = (
|
|||
}
|
||||
};
|
||||
|
||||
export const tryHexToNativeStringNear = async (
|
||||
provider: NearProvider,
|
||||
tokenBridge: string,
|
||||
address: string
|
||||
): Promise<string> => {
|
||||
const { found, value } = await hashLookup(provider, tokenBridge, address);
|
||||
if (!found) {
|
||||
throw new Error("Address not found");
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Convert an address in a wormhole's 32-byte hex representation into a chain's native
|
||||
|
@ -214,9 +228,7 @@ export const tryNativeToHexString = (
|
|||
} else if (chainId == CHAIN_ID_WORMHOLE_CHAIN) {
|
||||
return uint8ArrayToHex(zeroPad(canonicalAddress(address), 32));
|
||||
} else if (chainId === CHAIN_ID_NEAR) {
|
||||
return uint8ArrayToHex(
|
||||
zeroPad(new Uint8Array(Buffer.from(address, "ascii")), 32)
|
||||
);
|
||||
return uint8ArrayToHex(arrayify(sha256(Buffer.from(address))));
|
||||
} else if (chainId === CHAIN_ID_OSMOSIS) {
|
||||
throw Error("hexToNativeString: Osmosis not supported yet.");
|
||||
} else if (chainId === CHAIN_ID_SUI) {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import nearAPI from "near-api-js";
|
||||
import BN from "bn.js";
|
||||
import { Provider } from "near-api-js/lib/providers";
|
||||
import { CodeResult } from "near-api-js/lib/providers/provider";
|
||||
|
||||
export function logNearGas(result: any, comment: string) {
|
||||
const { totalGasBurned, totalTokensBurned } = result.receipts_outcome.reduce(
|
||||
|
@ -24,3 +27,69 @@ export function logNearGas(result: any, comment: string) {
|
|||
totalTokensBurned
|
||||
);
|
||||
}
|
||||
|
||||
export async function hashAccount(
|
||||
provider: Provider,
|
||||
tokenBridge: string,
|
||||
account: string
|
||||
): Promise<{ isRegistered: boolean; accountHash: string }> {
|
||||
// Near can have account names up to 64 bytes, but wormhole only supports 32
|
||||
// As a result, we have to hash our account names with sha256
|
||||
const [isRegistered, accountHash] = await callFunctionNear(
|
||||
provider,
|
||||
tokenBridge,
|
||||
"hash_account",
|
||||
{ account }
|
||||
);
|
||||
return {
|
||||
isRegistered,
|
||||
accountHash,
|
||||
};
|
||||
}
|
||||
|
||||
export async function hashLookup(
|
||||
provider: Provider,
|
||||
tokenBridge: string,
|
||||
hash: string
|
||||
): Promise<{ found: boolean; value: string }> {
|
||||
const [found, value] = await callFunctionNear(
|
||||
provider,
|
||||
tokenBridge,
|
||||
"hash_lookup",
|
||||
{
|
||||
hash,
|
||||
}
|
||||
);
|
||||
return {
|
||||
found,
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
export function registerAccount(account: string, tokenBridge: string) {
|
||||
return {
|
||||
contractId: tokenBridge,
|
||||
methodName: "register_account",
|
||||
args: { account },
|
||||
gas: new BN("100000000000000"),
|
||||
attachedDeposit: new BN("2000000000000000000000"),
|
||||
};
|
||||
}
|
||||
|
||||
export async function callFunctionNear(
|
||||
provider: Provider,
|
||||
accountId: string,
|
||||
methodName: string,
|
||||
args?: any
|
||||
) {
|
||||
const response = await provider.query<CodeResult>({
|
||||
request_type: "call_function",
|
||||
account_id: accountId,
|
||||
method_name: methodName,
|
||||
args_base64: args
|
||||
? Buffer.from(JSON.stringify(args)).toString("base64")
|
||||
: "",
|
||||
finality: "final",
|
||||
});
|
||||
return JSON.parse(Buffer.from(response.result).toString());
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ node build/main.js submit -c solana -n devnet "$REGISTER_TERRA_TOKEN_BRIDGE_VAA"
|
|||
node build/main.js submit -c solana -n devnet "$REGISTER_BSC_TOKEN_BRIDGE_VAA"
|
||||
node build/main.js submit -c solana -n devnet "$REGISTER_ALGO_TOKEN_BRIDGE_VAA"
|
||||
node build/main.js submit -c solana -n devnet "$REGISTER_TERRA2_TOKEN_BRIDGE_VAA"
|
||||
node build/main.js submit -c solana -n devnet "$REGISTER_NEAR_TOKEN_BRIDGE_VAA"
|
||||
# Register the NFT Bridge Endpoint on ETH
|
||||
node build/main.js submit -c solana -n devnet "$REGISTER_ETH_NFT_BRIDGE_VAA"
|
||||
node build/main.js submit -c solana -n devnet "$REGISTER_TERRA_NFT_BRIDGE_VAA"
|
||||
|
|
|
@ -268,6 +268,8 @@ const contract_registrations = {
|
|||
process.env.REGISTER_ALGO_TOKEN_BRIDGE_VAA,
|
||||
// TERRA2
|
||||
process.env.REGISTER_TERRA2_TOKEN_BRIDGE_VAA,
|
||||
// NEAR
|
||||
process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA,
|
||||
],
|
||||
"nft_bridge.wasm": [
|
||||
// Solana
|
||||
|
|
Loading…
Reference in New Issue