diff --git a/bridge/Dockerfile b/bridge/Dockerfile index b7d13fe..4a6345a 100644 --- a/bridge/Dockerfile +++ b/bridge/Dockerfile @@ -14,4 +14,4 @@ COPY --from=build-env /build/node_modules /app/node_modules COPY package.json /app WORKDIR /app -ENTRYPOINT ["npx", "tsx", "index.js"] +ENTRYPOINT ["npx", "tsx", "src/index.js"] diff --git a/bridge/package.json b/bridge/package.json index e8913ee..5a88f16 100644 --- a/bridge/package.json +++ b/bridge/package.json @@ -11,7 +11,7 @@ "coverage": "jest --coverage --config=./bridge.jest.config.js", "lint": "eslint src --ext .ts", "build": "tsc", - "mint": "node scripts/mint-script.js mint" + "transfer": "node scripts/transfer-script.js transfer" }, "repository": { "type": "git", @@ -64,12 +64,12 @@ }, "dependencies": { "@pagerduty/pdjs": "^2.2.3", - "@planetarium/account": "2.4.0", + "@planetarium/account": "4.0.6", "@planetarium/account-aws-kms": "^0.0.2", "@planetarium/aws-kms-provider": "0.3.4", "@planetarium/bencodex": "0.2.2", "@planetarium/sign": "^0.0.3", - "@planetarium/tx": "2.4.0", + "@planetarium/tx": "4.0.6", "@safe-global/safe-core-sdk": "^3.3.2", "@safe-global/safe-core-sdk-types": "^1.9.0", "@safe-global/safe-ethers-lib": "^1.9.2", diff --git a/bridge/scripts/transfer-script.ts b/bridge/scripts/transfer-script.ts new file mode 100644 index 0000000..7bb76c9 --- /dev/null +++ b/bridge/scripts/transfer-script.ts @@ -0,0 +1,143 @@ +"use strict"; +import { NCGKMSTransfer } from "../src/ncg-kms-transfer"; +import { KmsProvider } from "@planetarium/aws-kms-provider"; +import Web3 from "web3"; +import { HeadlessGraphQLClient } from "../src/headless-graphql-client"; +import { KMSNCGSigner } from "../src/kms-ncg-signer"; +import { isAddress } from "web3-utils"; +import { Command } from "commander"; +import readline from "readline"; + +async function transfer() { + const program = new Command(); + program + .name("[BSC Bridge] ad-hoc transfer script") + .description("Transfer token") + .version("0.0.1"); + + program + .command("transfer") + .description("transfer ( ad-hoc transfer )") + .argument("
", "destination( 9c address )") + .argument("", "amount( to transfer )") + .action(async (address: string, amount: string) => { + await transferNcg(address, amount); + }); + + program.parseAsync(); +} + +transfer(); + +async function transferNcg(user9cAddress: string, amount: string) { + if (Number(amount) > 100000) { + console.log("Cannot transfer over 100000 - Cancel transfer ..."); + process.exit(1); + } + + const isValidAddress = (address: string) => { + const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; + return ( + address.startsWith("0x") && isAddress(address) && address !== ZERO_ADDRESS + ); + }; + if (!isValidAddress(user9cAddress)) { + console.log("isValidAddress - Cancel transfer..."); + process.exit(1); + } + + const GRAPHQL_API_ENDPOINT = process.env.GRAPHQL_API_ENDPOINT!; + const NCG_MINTER = process.env.NCG_MINTER!; + + const KMS_PROVIDER_URL = process.env.KMS_PROVIDER_URL!; + const KMS_PROVIDER_REGION = process.env.KMS_PROVIDER_REGION!; + const KMS_PROVIDER_KEY_ID = process.env.KMS_PROVIDER_KEY_ID!; + const KMS_PROVIDER_AWS_ACCESSKEY = process.env.KMS_PROVIDER_AWS_ACCESSKEY!; + const KMS_PROVIDER_AWS_SECRETKEY = process.env.KMS_PROVIDER_AWS_SECRETKEY!; + const KMS_PROVIDER_PUBLIC_KEY = process.env.KMS_PROVIDER_PUBLIC_KEY!; + + const GRAPHQL_REQUEST_RETRY = 5; + const headlessGraphQLCLient = new HeadlessGraphQLClient( + GRAPHQL_API_ENDPOINT, + GRAPHQL_REQUEST_RETRY + ); + + const kmsProvider = new KmsProvider(KMS_PROVIDER_URL, { + region: KMS_PROVIDER_REGION, + keyIds: [KMS_PROVIDER_KEY_ID], + credential: { + accessKeyId: KMS_PROVIDER_AWS_ACCESSKEY, + secretAccessKey: KMS_PROVIDER_AWS_SECRETKEY, + }, + }); + const web3 = new Web3(kmsProvider); + + const kmsAddresses = await kmsProvider.getAccounts(); + if (kmsAddresses.length != 1) { + console.log("NineChronicles.BscBridge is supported only one address."); + process.exit(1); + } + const kmsAddress = kmsAddresses[0]; + console.log("kmsAddress", kmsAddress); + + const signer = new KMSNCGSigner(KMS_PROVIDER_REGION, KMS_PROVIDER_KEY_ID, { + accessKeyId: KMS_PROVIDER_AWS_ACCESSKEY, + secretAccessKey: KMS_PROVIDER_AWS_SECRETKEY, + }); + const derivedAddress = + "0x" + + web3.utils + .keccak256( + "0x" + + Buffer.from(KMS_PROVIDER_PUBLIC_KEY, "base64") + .toString("hex") + .slice(2) + ) + .slice(26); + if (kmsAddress.toLowerCase() !== derivedAddress.toLowerCase()) { + console.log( + "KMS_PROVIDER_PUBLIC_KEY variable seems invalid because it doesn't match to address from KMS." + ); + process.exit(1); + } + + const ncgKmsTransfer = new NCGKMSTransfer( + [headlessGraphQLCLient], + kmsAddress, + KMS_PROVIDER_PUBLIC_KEY, + [NCG_MINTER], + signer + ); + + console.log( + "===========================================================================================================" + ); + console.log( + `Are you trying to Transfer NCG. To: ${user9cAddress}, Amount: ${amount} ??` + ); + console.log('If Correct, Enter "yes", If not Enter anything'); + + const reader = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + await reader.on("line", async (input) => { + reader.close(); + + if (input.toLowerCase() !== "yes") { + console.log("Cancel Transferring...."); + process.exit(1); + } + + console.log(`Transferring NCG to ${user9cAddress}, amount: ${amount}...`); + + const txId = await ncgKmsTransfer.transfer( + user9cAddress, + amount.toString(), + null + ); + + console.log("txId", txId); + }); +} diff --git a/bridge/yarn.lock b/bridge/yarn.lock index b865783..2b98ef1 100644 --- a/bridge/yarn.lock +++ b/bridge/yarn.lock @@ -2664,10 +2664,10 @@ "@planetarium/sign" "^0.0.2" asn1js "^3.0.5" -"@planetarium/account@2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@planetarium/account/-/account-2.4.0.tgz#7f30eb92a28c6ce63fccf3fe18c920906272b300" - integrity sha512-P7tGmh8L4S8ZedXa7l0bodIoCh9Ml6E25Od4d2kTVYvK0o1TE6YYzMYoAI80B9ZLjfVbI5ZIZCoapu24rAGm8w== +"@planetarium/account@4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@planetarium/account/-/account-4.0.6.tgz#f3bb09dafc4af59080203896b4c5f78da6f951c1" + integrity sha512-+papVvf4L4A+UTV4LhlRb6VFjqitsESCeoRfGiR7hIkvrTpGHgjxrkLiAtk3dx6w9jjtFP5uav9d3vw4hh4dmw== dependencies: "@noble/hashes" "^1.2.0" "@noble/secp256k1" "^1.7.1" @@ -2711,10 +2711,10 @@ bencodex "^0.1.2" buffer "^6.0.3" -"@planetarium/tx@2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@planetarium/tx/-/tx-2.4.0.tgz#ee36fdfa8acd5ea95e11556c78ec390f60ffb908" - integrity sha512-g31KBglSr1z4wc5MYXQlWCz048p2RzAPDe1X1fUfKNIvEcW7jyNegggkIuKoFaKa2z8QMkxRJWd8AwgSXEB9rQ== +"@planetarium/tx@4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@planetarium/tx/-/tx-4.0.6.tgz#fee45c5b95b07c87ab9bfce36790077a9dc0cddf" + integrity sha512-haFVkGfyIxZjbi1GNcfS+I58mZD0zwgFz6Ib8Xa5uD31XJlg0/vdOf6D8TCbvGkljjGFv0l+D4Mf/bmeUnYEWg== dependencies: "@planetarium/bencodex" "^0.2.2"