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"