From 0b88d1cf6c0bae875bff984dce1c89e77108f949 Mon Sep 17 00:00:00 2001 From: akhilbidhuriBitGo Date: Wed, 28 Sep 2022 16:47:45 +0530 Subject: [PATCH] feat: add polygon to wrw Ticket: BG-48024 --- NON_BITGO_RECOVERY.md | 14 +- UNSIGNED_SWEEP.md | 18 +- electron/main/index.ts | 4 +- package-lock.json | 492 ++++++++++++++++++ package.json | 1 + scripts/build-icons.js | 1 + .../CoinsSelectAutocomplete.tsx | 12 + .../CryptocurrencyIcon/CryptocurrencyIcon.tsx | 21 +- .../BuildUnsignedSweepCoin.tsx | 75 +++ .../BuildUnsignedSweepCoin/PolygonForm.tsx | 153 ++++++ .../NonBitGoRecoveryCoin.tsx | 66 +++ .../NonBitGoRecoveryCoin/PolygonForm.tsx | 173 ++++++ 12 files changed, 1016 insertions(+), 14 deletions(-) create mode 100644 src/containers/BuildUnsignedSweepCoin/PolygonForm.tsx create mode 100644 src/containers/NonBitGoRecoveryCoin/PolygonForm.tsx diff --git a/NON_BITGO_RECOVERY.md b/NON_BITGO_RECOVERY.md index dd722969..63a67664 100644 --- a/NON_BITGO_RECOVERY.md +++ b/NON_BITGO_RECOVERY.md @@ -19,7 +19,7 @@ Build a transaction from a hot wallet using the KeyCard in order to recover fund 2. For Coins like Stellar, Ripple, and EOS, Root Address of the wallet needs to be provided. - 3. For Ethereum, Ethereum Proof of Work, ERC20 Token, and Avalanche C-Chain, Wallet Contract Address needs to be provided. This is the ETH or AVAXC address of the wallet contract. This is also the wallet's base address. + 3. For Ethereum, Ethereum Proof of Work, ERC20 Token, Avalanche C-Chain and Polygon, Wallet Contract Address needs to be provided. This is the ETH or AVAXC or Polygon address of the wallet contract. This is also the wallet's base address. For ERC20 Token, Token Contract Address needs to be provided. This is the address of the smart contract of the token to recover. This is unique to each token and is NOT your wallet address 6. You are asked to provide Wallet Passphrase. This is the password that you had set at the time of wallet creation. @@ -28,9 +28,9 @@ Build a transaction from a hot wallet using the KeyCard in order to recover fund 8. For UTXO based coins like Bitcoin, Litecoin, Dash, Zcash, Bitcoin Gold, Tron, and Bitcoin Cash, Address Scanning Factor needs to be provided. By default, it's value is 20 and can be changed if needed. The tool scans the addresses of the wallet to find the unspents. If it doesn't find unspents in 20 consecutive addresses, then it will stop scanning and generate a recovery transaction. For eg: If your funds are stuck in addresses with indices 10, 25 and 50 and you keep scanning factor as 20. Then the tool will stop after scanning till 46th index, because it didn't find unspents for 20 consecutive addresses from 26th address onwards. So in order to recover the funds in the address with 50th index, you will have to increase the scanning factor to a higher value. -9. For Ethereum, Ethereum Proof of Work, and ERC20 Token, Max Fee Per Gas Price and Max Priority Fee Per Gas in Gwei needs to be provided. The value should be between 1 Gwei and 2500 Gwei. The default is 20 Gwei for Max Fee Per Gas and 10 Gwei for Max Priority Fee Per Gas. If there is not enough Gwei in the backup key address gas tank, you will need to fund your backup key address. WRW will report the backup key address if there is not enough Gwei in it. +9. For Ethereum, Ethereum Proof of Work, Polygon, and ERC20 Token, Max Fee Per Gas Price and Max Priority Fee Per Gas in Gwei needs to be provided. The value should be between 1 Gwei and 2500 Gwei. The default is 20 Gwei for Max Fee Per Gas and 10 Gwei for Max Priority Fee Per Gas. If there is not enough Gwei in the backup key address gas tank, you will need to fund your backup key address. WRW will report the backup key address if there is not enough Gwei in it. -10. For Ethereum, Ethereum Proof of Work, ERC20 Token, and Avalanche C-Chain, Gas Limit needs to be provided. The value should be between 30,000 and 20,000,000. The default is 500,000 units of gas. +10. For Ethereum, Ethereum Proof of Work, ERC20 Token, Polygon and Avalanche C-Chain, Gas Limit needs to be provided. The value should be between 30,000 and 20,000,000. The default is 500,000 units of gas. 11. For Avalanche C-Chain, Gas Price needs to be provided. The value should be between 1 Gwei and 2500 Gwei. The default is 30 Gwei. @@ -42,9 +42,11 @@ Build a transaction from a hot wallet using the KeyCard in order to recover fund 15. For Avalanche C-Chain, the key is from https://snowtrace.io/. -16. The SDK determines the amount of Coin that can be recovered, and builds a fully signed transaction to send that amount to the Destination Address. +16. For Polygon, the key is from https://polygonscan.com/. -17. This completed transaction can be broadcasted on the network using a blockchain explorer to finish the recovery. +17. The SDK determines the amount of Coin that can be recovered, and builds a fully signed transaction to send that amount to the Destination Address. + +18. This completed transaction can be broadcasted on the network using a blockchain explorer to finish the recovery. Some blockchain explorers to broadcast the transaction are as follows: Avalanche C-Chain transactions: https://snowtrace.io/pushTx @@ -59,6 +61,8 @@ Build a transaction from a hot wallet using the KeyCard in order to recover fund Ethereum Proof of Work transactions: [ETHW.md](ETHW.md) + Polygon transactions: https://polygonscan.com/ + Ripple transactions: https://bithomp.com/submit/ Stellar transactions: https://laboratory.stellar.org/#txsubmitter?network=public diff --git a/UNSIGNED_SWEEP.md b/UNSIGNED_SWEEP.md index 8eaa9de7..a952a93a 100644 --- a/UNSIGNED_SWEEP.md +++ b/UNSIGNED_SWEEP.md @@ -20,16 +20,16 @@ Build an unsigned transaction from a cold wallet using the user and backup publi 2. For Coins like Stellar, Ripple, and EOS, Root Address of the wallet needs to be provided. - 3. For Ethereum, Ethereum Proof of Work, ERC20 Token, and Avalanche C-Chain, Wallet Contract Address needs to be provided. This is the ETH or AVAXC address of the wallet contract. This is also the wallet's base address. + 3. For Ethereum, Ethereum Proof of Work, ERC20 Token, Avalanche C-Chain, Polygon, Wallet Contract Address needs to be provided. This is the ETH or AVAXC or Polygon address of the wallet contract. This is also the wallet's base address. For ERC20 Token, Token Contract Address needs to be provided. This is the address of the smart contract of the token to recover. This is unique to each token and is NOT your wallet address 7. You are asked to provide the Destination Address (The address where you want to receive your recovered funds). 8. For UTXO based coins like Bitcoin, Litecoin, Dash, Zcash, Bitcoin Gold, Tron, and Bitcoin Cash, Address Scanning Factor needs to be provided. By default, it's value is 20 and can be changed if needed. The tool scans the addresses of the wallet to find the unspents. If it doesn't find unspents in 20 consecutive addresses, then it will stop scanning and generate a recovery transaction. For eg: If your funds are stuck in addresses with indices 10, 25 and 50 and you keep scanning factor as 20. Then the tool will stop after scanning till 46th index, because it didn't find unspents for 20 consecutive addresses from 26th address onwards. So in order to recover the funds in the address with 50th index, you will have to increase the scanning factor to a higher value. -9. For Ethereum, Ethereum Proof of Work, and ERC20 Token, Max Fee Per Gas Price and Max Priority Fee Per Gas in Gwei needs to be provided. The value should be between 1 Gwei and 2500 Gwei. The default is 20 Gwei for Max Fee Per Gas and 10 Gwei for Max Priority Fee Per Gas. If there is not enough Gwei in the backup key address gas tank, you will need to fund your backup key address. WRW will report the backup key address if there is not enough Gwei in it. +9. For Ethereum, Ethereum Proof of Work, Polygon, and ERC20 Token, Max Fee Per Gas Price and Max Priority Fee Per Gas in Gwei needs to be provided. The value should be between 1 Gwei and 2500 Gwei. The default is 20 Gwei for Max Fee Per Gas and 10 Gwei for Max Priority Fee Per Gas. If there is not enough Gwei in the backup key address gas tank, you will need to fund your backup key address. WRW will report the backup key address if there is not enough Gwei in it. -10. For Ethereum, Ethereum Proof of Work, ERC20 Token, and Avalanche C-Chain, Gas Limit needs to be provided. The value should be between 30,000 and 20,000,000. The default is 500,000 units of gas. +10. For Ethereum, Ethereum Proof of Work, ERC20 Token, Polygon, and Avalanche C-Chain, Gas Limit needs to be provided. The value should be between 30,000 and 20,000,000. The default is 500,000 units of gas. 11. For Avalanche C-Chain, Gas Price needs to be provided. The value should be between 1 Gwei and 2500 Gwei. The default is 30 Gwei. @@ -41,13 +41,15 @@ Build an unsigned transaction from a cold wallet using the user and backup publi 15. For Avalanche C-Chain, the key is from https://snowtrace.io/. -16. The SDK determines the amount of Coin that can be recovered, and builds an unsigned transaction to send that amount to the Destination Address. +16. For Polygon, the key is from https://polygon.com/. -17. You need to half sign this unsigned transaction with your user private key using Offline Vault Console. +17. The SDK determines the amount of Coin that can be recovered, and builds an unsigned transaction to send that amount to the Destination Address. -18. You need to fully sign the half signed transaction with your backup private key using Offline Vault Console. +18. You need to half sign this unsigned transaction with your user private key using Offline Vault Console. -19. This completed transaction can be broadcasted on the network using a blockchain explorer to finish the recovery. +19. You need to fully sign the half signed transaction with your backup private key using Offline Vault Console. + +20. This completed transaction can be broadcasted on the network using a blockchain explorer to finish the recovery. Some blockchain explorers to broadcast the transaction are as follows: Avalanche C-Chain transactions: https://snowtrace.io/pushTx @@ -62,6 +64,8 @@ Build an unsigned transaction from a cold wallet using the user and backup publi Ethereum Proof of Work transactions: [ETHW.md](ETHW.md) + Polygon transactions: https://polygonscan.com/ + Ripple transactions: https://bithomp.com/submit/ Stellar transactions: https://laboratory.stellar.org/#txsubmitter?network=public diff --git a/electron/main/index.ts b/electron/main/index.ts index c1767500..da608fa8 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -16,7 +16,7 @@ import { Trx, Ttrx } from '@bitgo/sdk-coin-trx'; import { Txlm, Xlm } from '@bitgo/sdk-coin-xlm'; import { Txrp, Xrp } from '@bitgo/sdk-coin-xrp'; import { Zec } from '@bitgo/sdk-coin-zec'; -import { IBaseCoin } from '@bitgo/sdk-core'; +import { Polygon, Tpolygon } from '@bitgo/sdk-coin-polygon'; import { fromBase58 } from 'bip32'; import { app, BrowserWindow, dialog, ipcMain, shell } from 'electron'; import fs from 'node:fs/promises'; @@ -72,6 +72,8 @@ sdk.register('trx', Trx.createInstance); sdk.register('ttrx', Ttrx.createInstance); sdk.register('avaxc', AvaxC.createInstance); sdk.register('tavaxc', TavaxC.createInstance); +sdk.register('polygon', Polygon.createInstance); +sdk.register('tpolygon', Tpolygon.createInstance); Erc20Token.createTokenConstructors().forEach(({ name, coinConstructor }) => { sdk.register(name, coinConstructor); }); diff --git a/package-lock.json b/package-lock.json index deb42f82..2918f7c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@bitgo/sdk-coin-eth": "^1.1.1", "@bitgo/sdk-coin-ethw": "^1.1.0-rc.19", "@bitgo/sdk-coin-ltc": "^1.1.1", + "@bitgo/sdk-coin-polygon": "^1.1.0-rc.33", "@bitgo/sdk-coin-trx": "^1.0.2", "@bitgo/sdk-coin-xlm": "^1.0.2", "@bitgo/sdk-coin-xrp": "^1.1.1", @@ -2931,6 +2932,269 @@ "node": ">=14 <17" } }, + "node_modules/@bitgo/sdk-coin-polygon": { + "version": "1.1.0-rc.35", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-polygon/-/sdk-coin-polygon-1.1.0-rc.35.tgz", + "integrity": "sha512-5fAGfeOa5FqXZZzBrvXKJE0zrwwpOJ+/1L6A6LTXqUNaJdp7fKFhIxYPsUsQUvxnq9jC5zPlObN9w/em3jvmRA==", + "dependencies": { + "@bitgo/abstract-eth": "^1.0.3-rc.37", + "@bitgo/sdk-coin-eth": "^2.0.0-rc.33", + "@bitgo/sdk-core": "^2.0.0-rc.33", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "@ethereumjs/common": "^2.4.0", + "@ethereumjs/tx": "^3.3.0", + "bignumber.js": "^9.0.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "lodash": "^4.17.14", + "superagent": "^3.8.3" + }, + "engines": { + "node": ">=14 <17" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/abstract-eth": { + "version": "1.0.3-rc.37", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-eth/-/abstract-eth-1.0.3-rc.37.tgz", + "integrity": "sha512-dZpTliLfIZR5LVMoZdWAXHiZHYVAMERdLKNx5kMmV+QQJp5nbRiPECke/zd0sH26cu1haGrNjtcYLIgnkXnDJA==", + "dependencies": { + "@bitgo/sdk-coin-eth": "^2.0.0-rc.33", + "@bitgo/sdk-core": "^2.0.0-rc.33", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "bignumber.js": "^8.0.1" + }, + "engines": { + "node": ">=14 <17" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/abstract-eth/node_modules/bignumber.js": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-8.1.1.tgz", + "integrity": "sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ==", + "engines": { + "node": "*" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/blake2b": { + "version": "3.0.4-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/blake2b/-/blake2b-3.0.4-rc.0.tgz", + "integrity": "sha512-/NVV3MY6szDM6gehfRRVZPQ9EmNVNVdnsWhibx+lgFq27z3UiU0ZCxItH03PGFFXSICRiH9xYb0SCOFm+Qn/uQ==", + "dependencies": { + "@bitgo/blake2b-wasm": "^3.0.4-rc.0", + "nanoassert": "^2.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/blake2b-wasm": { + "version": "3.0.4-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/blake2b-wasm/-/blake2b-wasm-3.0.4-rc.0.tgz", + "integrity": "sha512-HbwX9YpLjUDIDgA1Dp6KgNhrkF06Rplio/3QjVbOdrGcTRfWxKly38l0eHqMnlgIigPjG/UOpCCVBLMzkOkUbA==", + "dependencies": { + "nanoassert": "^1.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/blake2b-wasm/node_modules/nanoassert": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", + "integrity": "sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==" + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/sdk-coin-eth": { + "version": "2.0.0-rc.33", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eth/-/sdk-coin-eth-2.0.0-rc.33.tgz", + "integrity": "sha512-eHxSfjLpK9d7KjDE04o/ww9RwQE3k949g2lvJMJhBEvZPivQRHIhjLQ/zaj8Jy7tc8f1ntTWKySX0j9zv5Tn3w==", + "dependencies": { + "@bitgo/sdk-core": "^2.0.0-rc.33", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "@ethereumjs/common": "^2.4.0", + "@ethereumjs/tx": "^3.3.0", + "bignumber.js": "^9.0.0", + "bn.js": "^5.2.1", + "debug": "^3.1.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "ethers": "^5.1.3", + "keccak": "^3.0.2", + "lodash": "^4.17.14", + "secp256k1": "4.0.2", + "superagent": "^3.8.3" + }, + "engines": { + "node": ">=14 <17" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/sdk-core": { + "version": "2.0.0-rc.33", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-core/-/sdk-core-2.0.0-rc.33.tgz", + "integrity": "sha512-89BKgZLQBUPjh27dOa/1A0OX+nzRe54kKE1ZLXcx5yoVgol675ANCN3noJB8n6K3Dk8f/h+zibzYjsjbE835GQ==", + "dependencies": { + "@bitgo/bls-dkg": "^1.1.0", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "@noble/secp256k1": "1.6.3", + "@stablelib/hex": "^1.0.0", + "@types/keccak": "^3.0.1", + "bech32": "^2.0.0", + "big.js": "^3.1.3", + "bigint-crypto-utils": "3.1.4", + "bignumber.js": "^9.0.0", + "bitcoinjs-message": "^2.0.0", + "bolt11": "^1.4.0", + "bs58": "^4.0.1", + "create-hmac": "^1.1.7", + "debug": "^3.1.0", + "ethereumjs-util": "7.1.5", + "fp-ts": "^2.12.2", + "io-ts": "^2.2.17", + "keccak": "3.0.2", + "libsodium-wrappers-sumo": "^0.7.9", + "lodash": "^4.17.15", + "noble-bls12-381": "0.7.2", + "openpgp": "5.1.0", + "paillier-bigint": "3.3.0", + "secp256k1": "^4.0.2", + "strip-hex-prefix": "^1.0.0", + "superagent": "^3.8.3", + "tweetnacl": "^1.0.3" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/statics": { + "version": "8.0.0-rc.22", + "resolved": "https://registry.npmjs.org/@bitgo/statics/-/statics-8.0.0-rc.22.tgz", + "integrity": "sha512-puK/QHBSg7HllG08HZunNDVQhxkQDO3ZMT0UOCAxwPNibc/O8XEbmsk9WK9xBtOnl8BvlORE1DwJdRkjwhfB9Q==" + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@bitgo/utxo-lib": { + "version": "3.0.0-rc.8", + "resolved": "https://registry.npmjs.org/@bitgo/utxo-lib/-/utxo-lib-3.0.0-rc.8.tgz", + "integrity": "sha512-bckNm0WqDubxUgekcHz7YGcDCI7LVOqcf5lynlYKNVA4H4N0px5atOMQckANntr6dnRU8WBv/LUPCch4X+v+sw==", + "dependencies": { + "@bitgo/blake2b": "^3.0.4-rc.0", + "@noble/secp256k1": "1.6.3", + "bip174": "npm:@bitgo/bip174@3.0.0", + "bip32": "^3.0.1", + "bitcoin-ops": "^1.3.0", + "bitcoinjs-lib": "npm:@bitgo/bitcoinjs-lib@7.0.0-rc.1", + "bn.js": "^5.2.1", + "bs58check": "^2.1.2", + "cashaddress": "^1.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ecpair": "npm:@bitgo/ecpair@2.1.0-rc.0", + "elliptic": "^6.5.2", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2" + }, + "engines": { + "node": ">=10.22.0 <17", + "npm": ">=3.10.10" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@noble/secp256k1": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", + "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/bip174": { + "name": "@bitgo/bip174", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@bitgo/bip174/-/bip174-3.0.0.tgz", + "integrity": "sha512-Qv98vy6l1WgZwrxKx7IPYY91/+Z3tpALVSDn+Ic9qCsxygCq9gYw5eL8q3kd7LYTFLy/HgcqhcMOa83Spbp4JA==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/bip32": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.1.0.tgz", + "integrity": "sha512-eoeajYEzJ4d6yyVtby8C+XkCeKItiC4Mx56a0M9VaqTMC73SWOm4xVZG7SaR8e/yp4eSyky2XcBpH3DApPdu7Q==", + "dependencies": { + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/bitcoinjs-lib": { + "name": "@bitgo/bitcoinjs-lib", + "version": "7.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@bitgo/bitcoinjs-lib/-/bitcoinjs-lib-7.0.0-rc.1.tgz", + "integrity": "sha512-MmIdTWKVWvLNm5in1pMiD97du6x0R0ZEb5SMPmRbl+qOI19/xXnRc6UdguTcLhZYPkvACMAlpN5ZtfV4yZJqwg==", + "dependencies": { + "bech32": "^2.0.0", + "bip174": "npm:@bitgo/bip174@3.0.0", + "bs58check": "^2.1.2", + "create-hash": "^1.1.0", + "fastpriorityqueue": "^0.7.1", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2", + "wif": "^2.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/ecpair": { + "name": "@bitgo/ecpair", + "version": "2.1.0-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/ecpair/-/ecpair-2.1.0-rc.0.tgz", + "integrity": "sha512-qPZetcEA1Lzzm9NsqsGF9NGorAGaXrv20eZjopLUjsdwftWcsYTE7lwzE/Xjdf4fcq6G4+vjrCudWAMGNfJqOQ==", + "dependencies": { + "randombytes": "^2.1.0", + "typeforce": "^1.18.0", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node_modules/@bitgo/sdk-coin-polygon/node_modules/secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@bitgo/sdk-coin-trx": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-trx/-/sdk-coin-trx-1.0.2.tgz", @@ -38399,6 +38663,234 @@ "@bitgo/utxo-lib": "^2.4.1" } }, + "@bitgo/sdk-coin-polygon": { + "version": "1.1.0-rc.35", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-polygon/-/sdk-coin-polygon-1.1.0-rc.35.tgz", + "integrity": "sha512-5fAGfeOa5FqXZZzBrvXKJE0zrwwpOJ+/1L6A6LTXqUNaJdp7fKFhIxYPsUsQUvxnq9jC5zPlObN9w/em3jvmRA==", + "requires": { + "@bitgo/abstract-eth": "^1.0.3-rc.37", + "@bitgo/sdk-coin-eth": "^2.0.0-rc.33", + "@bitgo/sdk-core": "^2.0.0-rc.33", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "@ethereumjs/common": "^2.4.0", + "@ethereumjs/tx": "^3.3.0", + "bignumber.js": "^9.0.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "lodash": "^4.17.14", + "superagent": "^3.8.3" + }, + "dependencies": { + "@bitgo/abstract-eth": { + "version": "1.0.3-rc.37", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-eth/-/abstract-eth-1.0.3-rc.37.tgz", + "integrity": "sha512-dZpTliLfIZR5LVMoZdWAXHiZHYVAMERdLKNx5kMmV+QQJp5nbRiPECke/zd0sH26cu1haGrNjtcYLIgnkXnDJA==", + "requires": { + "@bitgo/sdk-coin-eth": "^2.0.0-rc.33", + "@bitgo/sdk-core": "^2.0.0-rc.33", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "bignumber.js": "^8.0.1" + }, + "dependencies": { + "bignumber.js": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-8.1.1.tgz", + "integrity": "sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ==" + } + } + }, + "@bitgo/blake2b": { + "version": "3.0.4-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/blake2b/-/blake2b-3.0.4-rc.0.tgz", + "integrity": "sha512-/NVV3MY6szDM6gehfRRVZPQ9EmNVNVdnsWhibx+lgFq27z3UiU0ZCxItH03PGFFXSICRiH9xYb0SCOFm+Qn/uQ==", + "requires": { + "@bitgo/blake2b-wasm": "^3.0.4-rc.0", + "nanoassert": "^2.0.0" + } + }, + "@bitgo/blake2b-wasm": { + "version": "3.0.4-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/blake2b-wasm/-/blake2b-wasm-3.0.4-rc.0.tgz", + "integrity": "sha512-HbwX9YpLjUDIDgA1Dp6KgNhrkF06Rplio/3QjVbOdrGcTRfWxKly38l0eHqMnlgIigPjG/UOpCCVBLMzkOkUbA==", + "requires": { + "nanoassert": "^1.0.0" + }, + "dependencies": { + "nanoassert": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", + "integrity": "sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==" + } + } + }, + "@bitgo/sdk-coin-eth": { + "version": "2.0.0-rc.33", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eth/-/sdk-coin-eth-2.0.0-rc.33.tgz", + "integrity": "sha512-eHxSfjLpK9d7KjDE04o/ww9RwQE3k949g2lvJMJhBEvZPivQRHIhjLQ/zaj8Jy7tc8f1ntTWKySX0j9zv5Tn3w==", + "requires": { + "@bitgo/sdk-core": "^2.0.0-rc.33", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "@ethereumjs/common": "^2.4.0", + "@ethereumjs/tx": "^3.3.0", + "bignumber.js": "^9.0.0", + "bn.js": "^5.2.1", + "debug": "^3.1.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "ethers": "^5.1.3", + "keccak": "^3.0.2", + "lodash": "^4.17.14", + "secp256k1": "4.0.2", + "superagent": "^3.8.3" + } + }, + "@bitgo/sdk-core": { + "version": "2.0.0-rc.33", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-core/-/sdk-core-2.0.0-rc.33.tgz", + "integrity": "sha512-89BKgZLQBUPjh27dOa/1A0OX+nzRe54kKE1ZLXcx5yoVgol675ANCN3noJB8n6K3Dk8f/h+zibzYjsjbE835GQ==", + "requires": { + "@bitgo/bls-dkg": "^1.1.0", + "@bitgo/statics": "^8.0.0-rc.22", + "@bitgo/utxo-lib": "^3.0.0-rc.8", + "@noble/secp256k1": "1.6.3", + "@stablelib/hex": "^1.0.0", + "@types/keccak": "^3.0.1", + "bech32": "^2.0.0", + "big.js": "^3.1.3", + "bigint-crypto-utils": "3.1.4", + "bignumber.js": "^9.0.0", + "bitcoinjs-message": "^2.0.0", + "bolt11": "^1.4.0", + "bs58": "^4.0.1", + "create-hmac": "^1.1.7", + "debug": "^3.1.0", + "ethereumjs-util": "7.1.5", + "fp-ts": "^2.12.2", + "io-ts": "^2.2.17", + "keccak": "3.0.2", + "libsodium-wrappers-sumo": "^0.7.9", + "lodash": "^4.17.15", + "noble-bls12-381": "0.7.2", + "openpgp": "5.1.0", + "paillier-bigint": "3.3.0", + "secp256k1": "^4.0.2", + "strip-hex-prefix": "^1.0.0", + "superagent": "^3.8.3", + "tweetnacl": "^1.0.3" + } + }, + "@bitgo/statics": { + "version": "8.0.0-rc.22", + "resolved": "https://registry.npmjs.org/@bitgo/statics/-/statics-8.0.0-rc.22.tgz", + "integrity": "sha512-puK/QHBSg7HllG08HZunNDVQhxkQDO3ZMT0UOCAxwPNibc/O8XEbmsk9WK9xBtOnl8BvlORE1DwJdRkjwhfB9Q==" + }, + "@bitgo/utxo-lib": { + "version": "3.0.0-rc.8", + "resolved": "https://registry.npmjs.org/@bitgo/utxo-lib/-/utxo-lib-3.0.0-rc.8.tgz", + "integrity": "sha512-bckNm0WqDubxUgekcHz7YGcDCI7LVOqcf5lynlYKNVA4H4N0px5atOMQckANntr6dnRU8WBv/LUPCch4X+v+sw==", + "requires": { + "@bitgo/blake2b": "^3.0.4-rc.0", + "@noble/secp256k1": "1.6.3", + "bip174": "npm:@bitgo/bip174@3.0.0", + "bip32": "^3.0.1", + "bitcoin-ops": "^1.3.0", + "bitcoinjs-lib": "npm:@bitgo/bitcoinjs-lib@7.0.0-rc.1", + "bn.js": "^5.2.1", + "bs58check": "^2.1.2", + "cashaddress": "^1.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ecpair": "npm:@bitgo/ecpair@2.1.0-rc.0", + "elliptic": "^6.5.2", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2" + } + }, + "@noble/secp256k1": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", + "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==" + }, + "bip174": { + "version": "npm:@bitgo/bip174@3.0.0", + "resolved": "https://registry.npmjs.org/@bitgo/bip174/-/bip174-3.0.0.tgz", + "integrity": "sha512-Qv98vy6l1WgZwrxKx7IPYY91/+Z3tpALVSDn+Ic9qCsxygCq9gYw5eL8q3kd7LYTFLy/HgcqhcMOa83Spbp4JA==" + }, + "bip32": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.1.0.tgz", + "integrity": "sha512-eoeajYEzJ4d6yyVtby8C+XkCeKItiC4Mx56a0M9VaqTMC73SWOm4xVZG7SaR8e/yp4eSyky2XcBpH3DApPdu7Q==", + "requires": { + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + } + }, + "bitcoinjs-lib": { + "version": "npm:@bitgo/bitcoinjs-lib@7.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@bitgo/bitcoinjs-lib/-/bitcoinjs-lib-7.0.0-rc.1.tgz", + "integrity": "sha512-MmIdTWKVWvLNm5in1pMiD97du6x0R0ZEb5SMPmRbl+qOI19/xXnRc6UdguTcLhZYPkvACMAlpN5ZtfV4yZJqwg==", + "requires": { + "bech32": "^2.0.0", + "bip174": "npm:@bitgo/bip174@3.0.0", + "bs58check": "^2.1.2", + "create-hash": "^1.1.0", + "fastpriorityqueue": "^0.7.1", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2", + "wif": "^2.0.1" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "requires": { + "base-x": "^3.0.2" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ecpair": { + "version": "npm:@bitgo/ecpair@2.1.0-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/ecpair/-/ecpair-2.1.0-rc.0.tgz", + "integrity": "sha512-qPZetcEA1Lzzm9NsqsGF9NGorAGaXrv20eZjopLUjsdwftWcsYTE7lwzE/Xjdf4fcq6G4+vjrCudWAMGNfJqOQ==", + "requires": { + "randombytes": "^2.1.0", + "typeforce": "^1.18.0", + "wif": "^2.0.6" + } + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "secp256k1": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + } + } + }, "@bitgo/sdk-coin-trx": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-trx/-/sdk-coin-trx-1.0.2.tgz", diff --git a/package.json b/package.json index a677b95e..368ad17e 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@bitgo/sdk-coin-xlm": "^1.0.2", "@bitgo/sdk-coin-xrp": "^1.1.1", "@bitgo/sdk-coin-zec": "^1.1.1", + "@bitgo/sdk-coin-polygon": "^1.1.0-rc.33", "@ethereumjs/common": "^2.6.5", "@lottiefiles/react-lottie-player": "^3.4.7", "clsx": "^1.2.1", diff --git a/scripts/build-icons.js b/scripts/build-icons.js index 69b65191..582a0380 100644 --- a/scripts/build-icons.js +++ b/scripts/build-icons.js @@ -17,6 +17,7 @@ const coins = [ 'bsv', 'eos', 'avax', + 'polygon', ]; const paths = fs diff --git a/src/components/CoinsSelectAutocomplete/CoinsSelectAutocomplete.tsx b/src/components/CoinsSelectAutocomplete/CoinsSelectAutocomplete.tsx index 7b10e506..dac0a00c 100644 --- a/src/components/CoinsSelectAutocomplete/CoinsSelectAutocomplete.tsx +++ b/src/components/CoinsSelectAutocomplete/CoinsSelectAutocomplete.tsx @@ -89,6 +89,12 @@ const prod = [ Icon: 'avax', value: 'avaxc', }, + { + Title: 'POLYGON', + Description: 'Polygon', + Icon: 'polygon', + value: 'polygon', + }, ] as const; const test = [ @@ -140,6 +146,12 @@ const test = [ Icon: 'avax', value: 'tavaxc', }, + { + Title: 'TPOLYGON', + Description: 'Testnet Polygon', + Icon: 'polygon', + value: 'tpolygon', + }, ] as const; export type CoinsSelectAutocompleteProps = { diff --git a/src/components/CryptocurrencyIcon/CryptocurrencyIcon.tsx b/src/components/CryptocurrencyIcon/CryptocurrencyIcon.tsx index dd706cf6..753b9684 100644 --- a/src/components/CryptocurrencyIcon/CryptocurrencyIcon.tsx +++ b/src/components/CryptocurrencyIcon/CryptocurrencyIcon.tsx @@ -13,7 +13,8 @@ export interface CryptocurrencyIconProps { | 'trx' | 'xlm' | 'xrp' - | 'zec'; + | 'zec' + | 'polygon'; Size: 'small' | 'medium' | 'large'; } @@ -320,6 +321,24 @@ export function CryptocurrencyIcon({ ); + case 'polygon': + return ( + + + + + + + ); default: return null; } diff --git a/src/containers/BuildUnsignedSweepCoin/BuildUnsignedSweepCoin.tsx b/src/containers/BuildUnsignedSweepCoin/BuildUnsignedSweepCoin.tsx index f9705b88..57a3547b 100644 --- a/src/containers/BuildUnsignedSweepCoin/BuildUnsignedSweepCoin.tsx +++ b/src/containers/BuildUnsignedSweepCoin/BuildUnsignedSweepCoin.tsx @@ -20,6 +20,7 @@ import { EthereumWForm } from './EthereumWForm'; import { LitecoinForm } from './LitecoinForm'; import { RippleForm } from './RippleForm'; import { TronForm } from './TronForm'; +import { PolygonForm } from './PolygonForm'; async function includePubsFor< TValues extends { @@ -695,6 +696,80 @@ function Form() { { encoding: 'utf-8' } ); + navigate( + `/${bitGoEnvironment}/build-unsigned-sweep/${coin}/success` + ); + } catch (err) { + if (err instanceof Error) { + setAlert(err.message); + } else { + console.error(err); + } + setSubmitting(false); + } + }} + /> + ); + case 'polygon': + case 'tpolygon': + return ( + { + setAlert(undefined); + setSubmitting(true); + try { + await window.commands.setBitGoEnvironment( + bitGoEnvironment, + values.apiKey + ); + const chainData = await window.queries.getChain(coin); + + const { maxFeePerGas, maxPriorityFeePerGas, ...rest } = + await updateKeysFromIds(coin, values); + const recoverData = await window.commands.recover(coin, { + ...rest, + eip1559: { + maxFeePerGas: toWei(maxFeePerGas), + maxPriorityFeePerGas: toWei(maxPriorityFeePerGas), + }, + bitgoKey: '', + ignoreAddressTypes: [], + }); + assert( + isRecoveryTransaction(recoverData), + 'Fully-signed recovery transaction not detected.' + ); + + const showSaveDialogData = await window.commands.showSaveDialog({ + filters: [ + { + name: 'Custom File Type', + extensions: ['json'], + }, + ], + defaultPath: `~/${chainData}-unsigned-sweep-${Date.now()}.json`, + }); + + if (!showSaveDialogData.filePath) { + throw new Error('No file path selected'); + } + + await window.commands.writeFile( + showSaveDialogData.filePath, + JSON.stringify( + includePubsInUnsignedSweep + ? { + ...recoverData, + ...(await includePubsFor(coin, values)), + } + : recoverData, + null, + 2 + ), + { encoding: 'utf-8' } + ); + navigate( `/${bitGoEnvironment}/build-unsigned-sweep/${coin}/success` ); diff --git a/src/containers/BuildUnsignedSweepCoin/PolygonForm.tsx b/src/containers/BuildUnsignedSweepCoin/PolygonForm.tsx new file mode 100644 index 00000000..0ce919b1 --- /dev/null +++ b/src/containers/BuildUnsignedSweepCoin/PolygonForm.tsx @@ -0,0 +1,153 @@ +import { Form, FormikHelpers, FormikProvider, useFormik } from 'formik'; +import { Link } from 'react-router-dom'; +import * as Yup from 'yup'; +import { Button, FormikTextfield } from '~/components'; + +const validationSchema = Yup.object({ + apiKey: Yup.string().required(), + backupKey: Yup.string().required(), + backupKeyId: Yup.string(), + gasLimit: Yup.number() + .typeError('Gas limit must be a number') + .integer() + .positive('Gas limit must be a positive integer') + .required(), + maxFeePerGas: Yup.number().required(), + maxPriorityFeePerGas: Yup.number().required(), + recoveryDestination: Yup.string().required(), + userKey: Yup.string().required(), + userKeyId: Yup.string(), + walletContractAddress: Yup.string().required(), +}).required(); + +export type PolygonFormProps = { + onSubmit: ( + values: PolygonFormValues, + formikHelpers: FormikHelpers + ) => void | Promise; +}; + +type PolygonFormValues = Yup.Asserts; + +export function PolygonForm({ onSubmit }: PolygonFormProps) { + const formik = useFormik({ + onSubmit, + initialValues: { + apiKey: '', + backupKey: '', + backupKeyId: '', + gasLimit: 500000, + maxFeePerGas: 20, + maxPriorityFeePerGas: 10, + recoveryDestination: '', + userKey: '', + userKeyId: '', + walletContractAddress: '', + }, + validationSchema, + }); + + return ( + +
+

+ Self-managed cold wallet details +

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
+ ); +} diff --git a/src/containers/NonBitGoRecoveryCoin/NonBitGoRecoveryCoin.tsx b/src/containers/NonBitGoRecoveryCoin/NonBitGoRecoveryCoin.tsx index 6f9f5ea0..82b0b8b0 100644 --- a/src/containers/NonBitGoRecoveryCoin/NonBitGoRecoveryCoin.tsx +++ b/src/containers/NonBitGoRecoveryCoin/NonBitGoRecoveryCoin.tsx @@ -19,6 +19,7 @@ import { EthereumWForm } from './EthereumWForm'; import { LitecoinForm } from './LitecoinForm'; import { RippleForm } from './RippleForm'; import { TronForm } from './TronForm'; +import { PolygonForm } from './PolygonForm'; function Form() { const { env, coin } = useParams<'env' | 'coin'>(); @@ -492,6 +493,71 @@ function Form() { { encoding: 'utf-8' } ); + navigate( + `/${bitGoEnvironment}/non-bitgo-recovery/${coin}/success` + ); + } catch (err) { + if (err instanceof Error) { + setAlert(err.message); + } else { + console.error(err); + } + setSubmitting(false); + } + }} + /> + ); + case 'polygon': + case 'tpolygon': + return ( + { + setAlert(undefined); + setSubmitting(true); + try { + await window.commands.setBitGoEnvironment( + bitGoEnvironment, + values.apiKey + ); + const chainData = await window.queries.getChain(coin); + + const { maxFeePerGas, maxPriorityFeePerGas, ...rest } = values; + + const recoverData = await window.commands.recover(coin, { + ...rest, + eip1559: { + maxFeePerGas: toWei(maxFeePerGas), + maxPriorityFeePerGas: toWei(maxPriorityFeePerGas), + }, + bitgoKey: '', + ignoreAddressTypes: [], + }); + assert( + isRecoveryTransaction(recoverData), + 'Fully-signed recovery transaction not detected.' + ); + + const showSaveDialogData = await window.commands.showSaveDialog({ + filters: [ + { + name: 'Custom File Type', + extensions: ['json'], + }, + ], + defaultPath: `~/${chainData}-recovery-${Date.now()}.json`, + }); + + if (!showSaveDialogData.filePath) { + throw new Error('No file path selected'); + } + + await window.commands.writeFile( + showSaveDialogData.filePath, + JSON.stringify(recoverData, null, 2), + { encoding: 'utf-8' } + ); + navigate( `/${bitGoEnvironment}/non-bitgo-recovery/${coin}/success` ); diff --git a/src/containers/NonBitGoRecoveryCoin/PolygonForm.tsx b/src/containers/NonBitGoRecoveryCoin/PolygonForm.tsx new file mode 100644 index 00000000..832d2cbb --- /dev/null +++ b/src/containers/NonBitGoRecoveryCoin/PolygonForm.tsx @@ -0,0 +1,173 @@ +import { Form, FormikHelpers, FormikProvider, useFormik } from 'formik'; +import { Link } from 'react-router-dom'; +import * as Yup from 'yup'; +import { + Button, + FormikSelectfield, + FormikTextarea, + FormikTextfield, +} from '~/components'; + +const validationSchema = Yup.object({ + apiKey: Yup.string().required(), + backupKey: Yup.string().required(), + gasLimit: Yup.number() + .typeError('Gas limit must be a number') + .integer() + .positive('Gas limit must be a positive integer') + .required(), + krsProvider: Yup.string() + .oneOf(['keyternal', 'bitgoKRSv2', 'dai']) + .label('Key Recovery Service'), + maxFeePerGas: Yup.number().required(), + maxPriorityFeePerGas: Yup.number().required(), + recoveryDestination: Yup.string().required(), + userKey: Yup.string().required(), + walletContractAddress: Yup.string().required(), + walletPassphrase: Yup.string().required(), +}).required(); + +export type PolygonFormProps = { + onSubmit: ( + values: PolygonFormValues, + formikHelpers: FormikHelpers + ) => void | Promise; +}; + +type PolygonFormValues = Yup.Asserts; + +export function PolygonForm({ onSubmit }: PolygonFormProps) { + const formik = useFormik({ + onSubmit, + initialValues: { + apiKey: '', + backupKey: '', + gasLimit: 500000, + krsProvider: '', + maxFeePerGas: 20, + maxPriorityFeePerGas: 10, + recoveryDestination: '', + userKey: '', + walletContractAddress: '', + walletPassphrase: '', + }, + validationSchema, + }); + + const backupKeyHelperText = + formik.values.krsProvider === '' + ? 'Your encrypted backup key, as found on your recovery KeyCard.' + : 'The backup public key for the wallet, as found on your recovery KeyCard.'; + + return ( + +
+

+ Self-managed hot wallet details +

+
+ + + + + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
+ ); +}