├── .drone.yml ├── .eslintrc.json ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .npmignore ├── README.md ├── eth ├── abis │ ├── Compound.json │ ├── CompoundComptroller.json │ ├── DSProxy.json │ ├── DSProxyActions.json │ ├── DSProxyActionsDsr.json │ ├── DSProxyFactory.json │ ├── DepositContract.json │ ├── DsrManager.json │ ├── Forwarder.json │ ├── ForwarderFactory.json │ ├── KashiPairMediumRiskV1.json │ ├── SkaleAllocator.json │ ├── SkaleDelegationController.json │ ├── SkaleDistributor.json │ ├── SkaleEscrow.json │ ├── SkaleTokenState.json │ ├── SkaleValidatorService.json │ ├── StandardERC20.json │ ├── SushiswapV2Router.json │ ├── UniswapV2SwapRouter.json │ ├── UniswapV3NonfungiblePositionManager.json │ ├── UniswapV3SwapRouter.json │ ├── WalletFactory.json │ ├── WalletSimple.json │ ├── WrappedToken.json │ ├── WrappedTokenController.json │ ├── WrappedTokenControllerV1.json │ ├── WrappedTokenFactory.json │ ├── WrappedTokenFactoryV1.json │ ├── WrappedTokenMembers.json │ └── index.ts ├── config │ └── instances.json └── examples │ ├── Compound │ ├── borrow.ts │ ├── lend.ts │ ├── redeemLend.ts │ └── repayBorrow.ts │ ├── DepositContract │ └── deposit.ts │ ├── MakerDAO │ ├── closeCDP.ts │ ├── createCDP.ts │ ├── depositSavingsRate.ts │ └── withdrawSavingsRate.ts │ ├── SKALE │ ├── bountiesEarned.ts │ ├── cancelPendingDelegation.ts │ ├── cancelPendingDelegationFromEscrow.ts │ ├── delegate.ts │ ├── delegateFromEscrow.ts │ ├── getEscrowAddress.ts │ ├── listDelegation.ts │ ├── listDelegationFromEscrow.ts │ ├── listValidators.ts │ ├── requestUndelegation.ts │ ├── requestUndelegationFromEscrow.ts │ ├── showLockedTokens.ts │ ├── showLockedTokensForEscrow.ts │ ├── withdrawBounty.ts │ └── withdrawBountyFromEscrow.ts │ ├── StandardERC20 │ ├── approve.ts │ └── transfer.ts │ ├── Sushiswap │ ├── createLiquidityPool.ts │ ├── kashiBorrow.ts │ ├── kashiLend.ts │ ├── removeLiquidityPool.ts │ └── swap.ts │ ├── Uniswap │ ├── createLiquidityPoolV2.ts │ ├── createLiquidityPoolV3.ts │ ├── removeLiquidityPoolV2.ts │ ├── removeLiquidityPoolV3.ts │ ├── swapV2.ts │ └── swapV3.ts │ ├── WrappedToken │ ├── balanceOf.ts │ ├── burn.ts │ ├── mint.ts │ └── transfer.ts │ ├── WrappedTokenControllerV1 │ └── transferOwnership.ts │ ├── WrappedTokenFactoryV1 │ └── addMintRequest.ts │ ├── WrappedTokenMembers │ └── setCustodian.ts │ └── utils.ts ├── package-lock.json ├── package.json ├── src ├── base │ ├── contracts │ │ ├── contractInstances.ts │ │ └── contracts.ts │ ├── decoder │ │ ├── decoder.ts │ │ └── types.ts │ ├── factory.ts │ └── methods │ │ └── methods.ts ├── eth │ ├── contracts │ │ └── contracts.ts │ ├── decoder │ │ ├── decoder.ts │ │ └── types.ts │ ├── factory.ts │ └── methods │ │ └── methods.ts ├── index.ts ├── trx │ ├── contracts │ │ └── contracts.ts │ ├── decoder │ │ ├── decoder.ts │ │ └── types.ts │ ├── factory.ts │ └── methods │ │ └── methods.ts └── util │ ├── ensure.ts │ └── string.ts ├── test ├── chain │ ├── base │ │ └── factory.test.ts │ ├── eth │ │ ├── contract.test.ts │ │ └── decoder.test.ts │ └── trx │ │ ├── contract.test.ts │ │ └── decoder.test.ts └── testutil.ts ├── trx ├── abis │ ├── WrappedToken.json │ ├── WrappedTokenController.json │ ├── WrappedTokenFactory.json │ ├── WrappedTokenMembers.json │ └── index.ts ├── config │ └── instances.json └── examples │ ├── WrappedToken │ ├── pause.ts │ └── transfer.ts │ ├── WrappedTokenFactory │ └── mintRequest.ts │ └── getContractList.ts ├── tsconfig.json └── webpack.config.js /.drone.yml: -------------------------------------------------------------------------------- 1 | pipeline: 2 | test: 3 | image: node:10.14 4 | commands: 5 | - npm install 6 | - npm test 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true, 6 | "mocha": true 7 | }, 8 | "globals": { 9 | "app": true, // BitGo side-effect from testutil 10 | "ethUtil": true // BitGo side-effect from testutil 11 | }, 12 | "parser": "@typescript-eslint/parser", 13 | "plugins": ["@typescript-eslint"], 14 | "extends": [ 15 | "eslint:recommended", 16 | "plugin:@typescript-eslint/recommended" 17 | ], 18 | "parserOptions": { 19 | "ecmaVersion": 8 20 | }, 21 | "rules": { 22 | "indent": ["error", 2, {"SwitchCase": 1, "MemberExpression": "off"}], 23 | "linebreak-style": ["error", "unix"], 24 | "semi": ["error", "always"], 25 | "eqeqeq": ["warn", "always"], 26 | "curly": "error", 27 | "no-extra-boolean-cast": "error", 28 | "object-curly-spacing": ["error", "always", {"objectsInObjects": true, "arraysInObjects": true}], 29 | "array-bracket-spacing": ["error", "never"], 30 | "require-yield": "off", 31 | "func-call-spacing": ["error", "never"], 32 | "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], 33 | "key-spacing": ["error", { "beforeColon": false, "afterColon": true, "mode": "strict" }], 34 | "quote-props": ["error", "as-needed"], 35 | "no-console": "off", 36 | "no-cond-assign": "error", 37 | "no-empty": ["error", { "allowEmptyCatch": false }], 38 | "no-inner-declarations": "off", 39 | "no-useless-escape": "off", 40 | "func-names": "off", 41 | "generator-star-spacing": ["error", {"before": true, "after": false}], 42 | "yield-star-spacing": ["error", {"before": true, "after": false}], 43 | "no-case-declarations": "off", 44 | "no-duplicate-imports": "error", // whilst imports are not being used, if we start to use them, we do not want duplicates 45 | "no-unreachable": "error", 46 | "no-path-concat": "off", 47 | "no-process-env": "off", 48 | "no-process-exit": "off", 49 | "no-sync": "off", 50 | "brace-style": ["error", "1tbs", { "allowSingleLine": true }], 51 | "eol-last": "error", 52 | "no-trailing-spaces": ["warn", { "skipBlankLines": true, "ignoreComments": true }], 53 | "no-unneeded-ternary": "error", 54 | "switch-colon-spacing": ["error", {"before": false, "after": true}], 55 | "arrow-spacing": ["error", { "before": true, "after": true }], 56 | "no-dupe-args": "error", 57 | "no-undef": "error", 58 | "no-var": "error", 59 | "prefer-const": "error", 60 | "no-const-assign": "error", 61 | "no-compare-neg-zero": "error", 62 | "no-extra-semi": "error", 63 | "radix": "error", 64 | "comma-spacing": ["error", { "before": false, "after": true }], 65 | "comma-dangle": ["error", "always-multiline"], 66 | "no-multi-spaces": ["error", {"ignoreEOLComments": true}], 67 | "keyword-spacing": ["error"], 68 | "space-before-blocks": ["error"], 69 | "space-infix-ops": ["error"], 70 | "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1 }], 71 | "multiline-comment-style": ["error", "starred-block"], 72 | "func-name-matching": ["error", { "includeCommonJSModuleExports": false }], 73 | "no-dupe-keys": "error", 74 | "no-irregular-whitespace": "error", 75 | "no-duplicate-case": "error", 76 | "@typescript-eslint/no-explicit-any": "off", 77 | "@typescript-eslint/explicit-module-boundary-types": "off", 78 | "@typescript-eslint/no-this-alias": "warn", 79 | "@typescript-eslint/no-var-requires": "off", 80 | "@typescript-eslint/no-unused-vars": ["error", { 81 | "vars": "all", 82 | "varsIgnorePattern": "^_", 83 | "args": "none", 84 | "argsIgnorePattern": "^_" 85 | /* TODO: enable this rule and fix errors 86 | "caughtErrors": "all", 87 | "caughtErrorsIgnorePattern": "^_" 88 | */ 89 | }], 90 | "@typescript-eslint/ban-ts-comment": ["error", { 91 | "ts-expect-error": "allow-with-description", 92 | "ts-ignore": "allow-with-description", 93 | "ts-nocheck": "allow-with-description", 94 | "ts-check": false 95 | }], 96 | "no-with": "error", 97 | "max-len": ["error", { 98 | "code": 160, 99 | "ignoreComments": true, 100 | "ignoreStrings": true, 101 | "ignoreTemplateLiterals": true, 102 | "ignoreRegExpLiterals": true 103 | }] 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 4 | on: 5 | pull_request: 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | matrix: 17 | node-version: [lts/-2, lts/-1] 18 | 19 | name: Node.js ${{ matrix.node-version }} 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v3 23 | 24 | - name: Configure Node.js 25 | uses: actions/setup-node@v3 26 | with: 27 | cache: npm 28 | node-version: ${{ matrix.node-version }} 29 | 30 | # Install npm greater-than-or-equal-to 7 for consistent dependency resolution. 31 | # We can remove this when Node.js 16 is the oldest LTS (2023-04-30). 32 | - name: Update npm 33 | run: npm install --global 'npm@>7' 34 | 35 | - name: Cache node_modules 36 | uses: actions/cache@v3 37 | id: cache-node-modules 38 | with: 39 | path: node_modules 40 | key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} 41 | 42 | - name: Install dependencies 43 | if: steps.cache-node-modules.outputs.cache-hit != 'true' 44 | run: npm ci 45 | 46 | - name: Compile TypeScript 47 | run: npm run build 48 | 49 | - name: Test 50 | run: npm test 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.swp 10 | 11 | pids 12 | logs 13 | results 14 | tmp 15 | env_file 16 | 17 | # Build 18 | public/css/main.css 19 | 20 | # Coverage reports 21 | coverage 22 | .nyc_output 23 | 24 | # API keys and secrets 25 | .env 26 | .platformProxyKey 27 | 28 | # Dependency directory 29 | node_modules 30 | bower_components 31 | 32 | # Editors 33 | .angulardoc.json 34 | .idea 35 | *.iml 36 | 37 | # OS metadata 38 | .DS_Store 39 | Thumbs.db 40 | 41 | # Ignore editor settings 42 | .vscode 43 | 44 | # Sandbox folder for testing 45 | lab/ 46 | 47 | # Debugging logs 48 | npm-debug.log 49 | lerna-debug.log 50 | 51 | # NPM lockfile 52 | yarn.lock 53 | 54 | # Symlinked postgres createDB.sh for packages 55 | packages/common/scripts/createDB.sh 56 | !packages/common/scripts/createDB.sh 57 | 58 | # Symlinked createTimescaleDB.sh for packages 59 | packages/common/scripts/createTimescaleDB.sh 60 | !packages/common/scripts/createTimescaleDB.sh 61 | 62 | # Cypress example files 63 | packages/cypress/fixtures/example.json 64 | 65 | # Cypress environment specific values 66 | packages/cypress.env.json 67 | 68 | # Cypress screenshots and videos 69 | packages/cypress/screenshots/ 70 | packages/cypress/snapshots/**/__diff_output__ 71 | packages/cypress/videos/ 72 | 73 | # these files get created by the local UI runner 74 | packages/cypress/package.json 75 | packages/cypress/package-lock.json 76 | 77 | #copied files from client-all 78 | packages/client-all/src/assets/ 79 | .eslintcache 80 | dist/ 81 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /eth/ 2 | /src/ 3 | /test/ 4 | /trx/ 5 | .drone.yml 6 | .eslintrc.json 7 | tsconfig.json 8 | 9 | -------------------------------------------------------------------------------- /eth/abis/DSProxy.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "owner_", 7 | "type": "address" 8 | } 9 | ], 10 | "name": "setOwner", 11 | "outputs": [], 12 | "payable": false, 13 | "stateMutability": "nonpayable", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [ 19 | { 20 | "name": "_target", 21 | "type": "address" 22 | }, 23 | { 24 | "name": "_data", 25 | "type": "bytes" 26 | } 27 | ], 28 | "name": "execute", 29 | "outputs": [ 30 | { 31 | "name": "response", 32 | "type": "bytes32" 33 | } 34 | ], 35 | "payable": true, 36 | "stateMutability": "payable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": false, 41 | "inputs": [ 42 | { 43 | "name": "_code", 44 | "type": "bytes" 45 | }, 46 | { 47 | "name": "_data", 48 | "type": "bytes" 49 | } 50 | ], 51 | "name": "execute", 52 | "outputs": [ 53 | { 54 | "name": "target", 55 | "type": "address" 56 | }, 57 | { 58 | "name": "response", 59 | "type": "bytes32" 60 | } 61 | ], 62 | "payable": true, 63 | "stateMutability": "payable", 64 | "type": "function" 65 | }, 66 | { 67 | "constant": true, 68 | "inputs": [], 69 | "name": "cache", 70 | "outputs": [ 71 | { 72 | "name": "", 73 | "type": "address" 74 | } 75 | ], 76 | "payable": false, 77 | "stateMutability": "view", 78 | "type": "function" 79 | }, 80 | { 81 | "constant": false, 82 | "inputs": [ 83 | { 84 | "name": "authority_", 85 | "type": "address" 86 | } 87 | ], 88 | "name": "setAuthority", 89 | "outputs": [], 90 | "payable": false, 91 | "stateMutability": "nonpayable", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [], 97 | "name": "owner", 98 | "outputs": [ 99 | { 100 | "name": "", 101 | "type": "address" 102 | } 103 | ], 104 | "payable": false, 105 | "stateMutability": "view", 106 | "type": "function" 107 | }, 108 | { 109 | "constant": false, 110 | "inputs": [ 111 | { 112 | "name": "_cacheAddr", 113 | "type": "address" 114 | } 115 | ], 116 | "name": "setCache", 117 | "outputs": [ 118 | { 119 | "name": "", 120 | "type": "bool" 121 | } 122 | ], 123 | "payable": false, 124 | "stateMutability": "nonpayable", 125 | "type": "function" 126 | }, 127 | { 128 | "constant": true, 129 | "inputs": [], 130 | "name": "authority", 131 | "outputs": [ 132 | { 133 | "name": "", 134 | "type": "address" 135 | } 136 | ], 137 | "payable": false, 138 | "stateMutability": "view", 139 | "type": "function" 140 | }, 141 | { 142 | "inputs": [ 143 | { 144 | "name": "_cacheAddr", 145 | "type": "address" 146 | } 147 | ], 148 | "payable": false, 149 | "stateMutability": "nonpayable", 150 | "type": "constructor" 151 | }, 152 | { 153 | "payable": true, 154 | "stateMutability": "payable", 155 | "type": "fallback" 156 | }, 157 | { 158 | "anonymous": true, 159 | "inputs": [ 160 | { 161 | "indexed": true, 162 | "name": "sig", 163 | "type": "bytes4" 164 | }, 165 | { 166 | "indexed": true, 167 | "name": "guy", 168 | "type": "address" 169 | }, 170 | { 171 | "indexed": true, 172 | "name": "foo", 173 | "type": "bytes32" 174 | }, 175 | { 176 | "indexed": true, 177 | "name": "bar", 178 | "type": "bytes32" 179 | }, 180 | { 181 | "indexed": false, 182 | "name": "wad", 183 | "type": "uint256" 184 | }, 185 | { 186 | "indexed": false, 187 | "name": "fax", 188 | "type": "bytes" 189 | } 190 | ], 191 | "name": "LogNote", 192 | "type": "event" 193 | }, 194 | { 195 | "anonymous": false, 196 | "inputs": [ 197 | { 198 | "indexed": true, 199 | "name": "authority", 200 | "type": "address" 201 | } 202 | ], 203 | "name": "LogSetAuthority", 204 | "type": "event" 205 | }, 206 | { 207 | "anonymous": false, 208 | "inputs": [ 209 | { 210 | "indexed": true, 211 | "name": "owner", 212 | "type": "address" 213 | } 214 | ], 215 | "name": "LogSetOwner", 216 | "type": "event" 217 | } 218 | ] 219 | -------------------------------------------------------------------------------- /eth/abis/DSProxyActionsDsr.json: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"internalType":"address","name":"apt","type":"address"},{"internalType":"address","name":"urn","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"daiJoin_join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"daiJoin","type":"address"},{"internalType":"address","name":"pot","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"daiJoin","type":"address"},{"internalType":"address","name":"pot","type":"address"}],"name":"exitAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"daiJoin","type":"address"},{"internalType":"address","name":"pot","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] 2 | -------------------------------------------------------------------------------- /eth/abis/DSProxyFactory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [], 5 | "name": "build", 6 | "outputs": [ 7 | { 8 | "name": "proxy", 9 | "type": "address" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "nonpayable", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": true, 18 | "inputs": [ 19 | { 20 | "name": "", 21 | "type": "address" 22 | } 23 | ], 24 | "name": "proxies", 25 | "outputs": [ 26 | { 27 | "name": "", 28 | "type": "address" 29 | } 30 | ], 31 | "payable": false, 32 | "stateMutability": "view", 33 | "type": "function" 34 | }, 35 | { 36 | "constant": false, 37 | "inputs": [ 38 | { 39 | "name": "owner", 40 | "type": "address" 41 | } 42 | ], 43 | "name": "build", 44 | "outputs": [ 45 | { 46 | "name": "proxy", 47 | "type": "address" 48 | } 49 | ], 50 | "payable": false, 51 | "stateMutability": "nonpayable", 52 | "type": "function" 53 | }, 54 | { 55 | "inputs": [ 56 | { 57 | "name": "factory_", 58 | "type": "address" 59 | } 60 | ], 61 | "payable": false, 62 | "stateMutability": "nonpayable", 63 | "type": "constructor" 64 | } 65 | ] 66 | -------------------------------------------------------------------------------- /eth/abis/DepositContract.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "anonymous": false, 9 | "inputs": [ 10 | { 11 | "indexed": false, 12 | "internalType": "bytes32", 13 | "name": "data", 14 | "type": "bytes32" 15 | } 16 | ], 17 | "name": "Debug", 18 | "type": "event" 19 | }, 20 | { 21 | "anonymous": false, 22 | "inputs": [ 23 | { 24 | "indexed": false, 25 | "internalType": "bytes", 26 | "name": "pubkey", 27 | "type": "bytes" 28 | }, 29 | { 30 | "indexed": false, 31 | "internalType": "bytes", 32 | "name": "withdrawal_credentials", 33 | "type": "bytes" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "bytes", 38 | "name": "amount", 39 | "type": "bytes" 40 | }, 41 | { 42 | "indexed": false, 43 | "internalType": "bytes", 44 | "name": "signature", 45 | "type": "bytes" 46 | }, 47 | { 48 | "indexed": false, 49 | "internalType": "bytes", 50 | "name": "index", 51 | "type": "bytes" 52 | } 53 | ], 54 | "name": "DepositEvent", 55 | "type": "event" 56 | }, 57 | { 58 | "inputs": [ 59 | { 60 | "internalType": "bytes", 61 | "name": "pubkey", 62 | "type": "bytes" 63 | }, 64 | { 65 | "internalType": "bytes", 66 | "name": "withdrawal_credentials", 67 | "type": "bytes" 68 | }, 69 | { 70 | "internalType": "bytes", 71 | "name": "signature", 72 | "type": "bytes" 73 | }, 74 | { 75 | "internalType": "bytes32", 76 | "name": "deposit_data_root", 77 | "type": "bytes32" 78 | } 79 | ], 80 | "name": "deposit", 81 | "outputs": [], 82 | "stateMutability": "payable", 83 | "type": "function" 84 | }, 85 | { 86 | "inputs": [], 87 | "name": "get_deposit_count", 88 | "outputs": [ 89 | { 90 | "internalType": "bytes", 91 | "name": "", 92 | "type": "bytes" 93 | } 94 | ], 95 | "stateMutability": "view", 96 | "type": "function" 97 | }, 98 | { 99 | "inputs": [], 100 | "name": "get_deposit_root", 101 | "outputs": [ 102 | { 103 | "internalType": "bytes32", 104 | "name": "", 105 | "type": "bytes32" 106 | } 107 | ], 108 | "stateMutability": "view", 109 | "type": "function" 110 | }, 111 | { 112 | "inputs": [ 113 | { 114 | "internalType": "bytes4", 115 | "name": "interfaceId", 116 | "type": "bytes4" 117 | } 118 | ], 119 | "name": "supportsInterface", 120 | "outputs": [ 121 | { 122 | "internalType": "bool", 123 | "name": "", 124 | "type": "bool" 125 | } 126 | ], 127 | "stateMutability": "pure", 128 | "type": "function" 129 | } 130 | ] 131 | -------------------------------------------------------------------------------- /eth/abis/DsrManager.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"pot_","type":"address"},{"internalType":"address","name":"daiJoin_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Exit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Join","type":"event"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"daiBalance","outputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"daiJoin","outputs":[{"internalType":"contract JoinLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"}],"name":"exitAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pieOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pot","outputs":[{"internalType":"contract PotLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}] 2 | -------------------------------------------------------------------------------- /eth/abis/Forwarder.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "toAddress", 7 | "type": "address" 8 | }, 9 | { 10 | "name": "value", 11 | "type": "uint256" 12 | }, 13 | { 14 | "name": "tokenContractAddress", 15 | "type": "address" 16 | }, 17 | { 18 | "name": "expireTime", 19 | "type": "uint256" 20 | }, 21 | { 22 | "name": "sequenceId", 23 | "type": "uint256" 24 | }, 25 | { 26 | "name": "signature", 27 | "type": "bytes" 28 | } 29 | ], 30 | "name": "sendMultiSigToken", 31 | "outputs": [], 32 | "payable": false, 33 | "stateMutability": "nonpayable", 34 | "type": "function" 35 | }, 36 | { 37 | "constant": true, 38 | "inputs": [ 39 | { 40 | "name": "", 41 | "type": "uint256" 42 | } 43 | ], 44 | "name": "signers", 45 | "outputs": [ 46 | { 47 | "name": "", 48 | "type": "address" 49 | } 50 | ], 51 | "payable": false, 52 | "stateMutability": "view", 53 | "type": "function" 54 | }, 55 | { 56 | "constant": false, 57 | "inputs": [ 58 | { 59 | "name": "forwarderAddress", 60 | "type": "address" 61 | }, 62 | { 63 | "name": "tokenContractAddress", 64 | "type": "address" 65 | } 66 | ], 67 | "name": "flushForwarderTokens", 68 | "outputs": [], 69 | "payable": false, 70 | "stateMutability": "nonpayable", 71 | "type": "function" 72 | }, 73 | { 74 | "constant": false, 75 | "inputs": [ 76 | { 77 | "name": "toAddress", 78 | "type": "address" 79 | }, 80 | { 81 | "name": "value", 82 | "type": "uint256" 83 | }, 84 | { 85 | "name": "data", 86 | "type": "bytes" 87 | }, 88 | { 89 | "name": "expireTime", 90 | "type": "uint256" 91 | }, 92 | { 93 | "name": "sequenceId", 94 | "type": "uint256" 95 | }, 96 | { 97 | "name": "signature", 98 | "type": "bytes" 99 | } 100 | ], 101 | "name": "sendMultiSig", 102 | "outputs": [], 103 | "payable": false, 104 | "stateMutability": "nonpayable", 105 | "type": "function" 106 | }, 107 | { 108 | "constant": true, 109 | "inputs": [ 110 | { 111 | "name": "signer", 112 | "type": "address" 113 | } 114 | ], 115 | "name": "isSigner", 116 | "outputs": [ 117 | { 118 | "name": "", 119 | "type": "bool" 120 | } 121 | ], 122 | "payable": false, 123 | "stateMutability": "view", 124 | "type": "function" 125 | }, 126 | { 127 | "constant": true, 128 | "inputs": [], 129 | "name": "getNextSequenceId", 130 | "outputs": [ 131 | { 132 | "name": "", 133 | "type": "uint256" 134 | } 135 | ], 136 | "payable": false, 137 | "stateMutability": "view", 138 | "type": "function" 139 | }, 140 | { 141 | "constant": false, 142 | "inputs": [], 143 | "name": "createForwarder", 144 | "outputs": [ 145 | { 146 | "name": "", 147 | "type": "address" 148 | } 149 | ], 150 | "payable": false, 151 | "stateMutability": "nonpayable", 152 | "type": "function" 153 | }, 154 | { 155 | "constant": true, 156 | "inputs": [], 157 | "name": "safeMode", 158 | "outputs": [ 159 | { 160 | "name": "", 161 | "type": "bool" 162 | } 163 | ], 164 | "payable": false, 165 | "stateMutability": "view", 166 | "type": "function" 167 | }, 168 | { 169 | "constant": false, 170 | "inputs": [], 171 | "name": "activateSafeMode", 172 | "outputs": [], 173 | "payable": false, 174 | "stateMutability": "nonpayable", 175 | "type": "function" 176 | }, 177 | { 178 | "inputs": [ 179 | { 180 | "name": "allowedSigners", 181 | "type": "address[]" 182 | } 183 | ], 184 | "payable": false, 185 | "stateMutability": "nonpayable", 186 | "type": "constructor" 187 | }, 188 | { 189 | "payable": true, 190 | "stateMutability": "payable", 191 | "type": "fallback" 192 | }, 193 | { 194 | "anonymous": false, 195 | "inputs": [ 196 | { 197 | "indexed": false, 198 | "name": "from", 199 | "type": "address" 200 | }, 201 | { 202 | "indexed": false, 203 | "name": "value", 204 | "type": "uint256" 205 | }, 206 | { 207 | "indexed": false, 208 | "name": "data", 209 | "type": "bytes" 210 | } 211 | ], 212 | "name": "Deposited", 213 | "type": "event" 214 | }, 215 | { 216 | "anonymous": false, 217 | "inputs": [ 218 | { 219 | "indexed": false, 220 | "name": "msgSender", 221 | "type": "address" 222 | } 223 | ], 224 | "name": "SafeModeActivated", 225 | "type": "event" 226 | }, 227 | { 228 | "anonymous": false, 229 | "inputs": [ 230 | { 231 | "indexed": false, 232 | "name": "msgSender", 233 | "type": "address" 234 | }, 235 | { 236 | "indexed": false, 237 | "name": "otherSigner", 238 | "type": "address" 239 | }, 240 | { 241 | "indexed": false, 242 | "name": "operation", 243 | "type": "bytes32" 244 | }, 245 | { 246 | "indexed": false, 247 | "name": "toAddress", 248 | "type": "address" 249 | }, 250 | { 251 | "indexed": false, 252 | "name": "value", 253 | "type": "uint256" 254 | }, 255 | { 256 | "indexed": false, 257 | "name": "data", 258 | "type": "bytes" 259 | } 260 | ], 261 | "name": "Transacted", 262 | "type": "event" 263 | } 264 | ] 265 | -------------------------------------------------------------------------------- /eth/abis/ForwarderFactory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_implementationAddress", 7 | "type": "address" 8 | } 9 | ], 10 | "stateMutability": "nonpayable", 11 | "type": "constructor" 12 | }, 13 | { 14 | "anonymous": false, 15 | "inputs": [ 16 | { 17 | "indexed": false, 18 | "internalType": "address", 19 | "name": "newForwarderAddress", 20 | "type": "address" 21 | }, 22 | { 23 | "indexed": false, 24 | "internalType": "address", 25 | "name": "parentAddress", 26 | "type": "address" 27 | } 28 | ], 29 | "name": "ForwarderCreated", 30 | "type": "event" 31 | }, 32 | { 33 | "inputs": [], 34 | "name": "implementationAddress", 35 | "outputs": [ 36 | { 37 | "internalType": "address", 38 | "name": "", 39 | "type": "address" 40 | } 41 | ], 42 | "stateMutability": "view", 43 | "type": "function" 44 | }, 45 | { 46 | "inputs": [ 47 | { 48 | "internalType": "address", 49 | "name": "parent", 50 | "type": "address" 51 | }, 52 | { 53 | "internalType": "bytes32", 54 | "name": "salt", 55 | "type": "bytes32" 56 | } 57 | ], 58 | "name": "createForwarder", 59 | "outputs": [], 60 | "stateMutability": "nonpayable", 61 | "type": "function" 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /eth/abis/StandardERC20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "_spender", 7 | "type": "address" 8 | }, 9 | { 10 | "name": "_value", 11 | "type": "uint256" 12 | } 13 | ], 14 | "name": "approve", 15 | "outputs": [ 16 | { 17 | "name": "", 18 | "type": "bool" 19 | } 20 | ], 21 | "payable": false, 22 | "stateMutability": "nonpayable", 23 | "type": "function" 24 | }, 25 | { 26 | "constant": true, 27 | "inputs": [], 28 | "name": "totalSupply", 29 | "outputs": [ 30 | { 31 | "name": "", 32 | "type": "uint256" 33 | } 34 | ], 35 | "payable": false, 36 | "stateMutability": "view", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": false, 41 | "inputs": [ 42 | { 43 | "name": "_from", 44 | "type": "address" 45 | }, 46 | { 47 | "name": "_to", 48 | "type": "address" 49 | }, 50 | { 51 | "name": "_value", 52 | "type": "uint256" 53 | } 54 | ], 55 | "name": "transferFrom", 56 | "outputs": [ 57 | { 58 | "name": "", 59 | "type": "bool" 60 | } 61 | ], 62 | "payable": false, 63 | "stateMutability": "nonpayable", 64 | "type": "function" 65 | }, 66 | { 67 | "constant": false, 68 | "inputs": [ 69 | { 70 | "name": "_spender", 71 | "type": "address" 72 | }, 73 | { 74 | "name": "_subtractedValue", 75 | "type": "uint256" 76 | } 77 | ], 78 | "name": "decreaseApproval", 79 | "outputs": [ 80 | { 81 | "name": "", 82 | "type": "bool" 83 | } 84 | ], 85 | "payable": false, 86 | "stateMutability": "nonpayable", 87 | "type": "function" 88 | }, 89 | { 90 | "constant": true, 91 | "inputs": [ 92 | { 93 | "name": "_owner", 94 | "type": "address" 95 | } 96 | ], 97 | "name": "balanceOf", 98 | "outputs": [ 99 | { 100 | "name": "", 101 | "type": "uint256" 102 | } 103 | ], 104 | "payable": false, 105 | "stateMutability": "view", 106 | "type": "function" 107 | }, 108 | { 109 | "constant": false, 110 | "inputs": [ 111 | { 112 | "name": "_to", 113 | "type": "address" 114 | }, 115 | { 116 | "name": "_value", 117 | "type": "uint256" 118 | } 119 | ], 120 | "name": "transfer", 121 | "outputs": [ 122 | { 123 | "name": "", 124 | "type": "bool" 125 | } 126 | ], 127 | "payable": false, 128 | "stateMutability": "nonpayable", 129 | "type": "function" 130 | }, 131 | { 132 | "constant": false, 133 | "inputs": [ 134 | { 135 | "name": "_spender", 136 | "type": "address" 137 | }, 138 | { 139 | "name": "_addedValue", 140 | "type": "uint256" 141 | } 142 | ], 143 | "name": "increaseApproval", 144 | "outputs": [ 145 | { 146 | "name": "", 147 | "type": "bool" 148 | } 149 | ], 150 | "payable": false, 151 | "stateMutability": "nonpayable", 152 | "type": "function" 153 | }, 154 | { 155 | "constant": true, 156 | "inputs": [ 157 | { 158 | "name": "_owner", 159 | "type": "address" 160 | }, 161 | { 162 | "name": "_spender", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "allowance", 167 | "outputs": [ 168 | { 169 | "name": "", 170 | "type": "uint256" 171 | } 172 | ], 173 | "payable": false, 174 | "stateMutability": "view", 175 | "type": "function" 176 | }, 177 | { 178 | "anonymous": false, 179 | "inputs": [ 180 | { 181 | "indexed": true, 182 | "name": "owner", 183 | "type": "address" 184 | }, 185 | { 186 | "indexed": true, 187 | "name": "spender", 188 | "type": "address" 189 | }, 190 | { 191 | "indexed": false, 192 | "name": "value", 193 | "type": "uint256" 194 | } 195 | ], 196 | "name": "Approval", 197 | "type": "event" 198 | }, 199 | { 200 | "anonymous": false, 201 | "inputs": [ 202 | { 203 | "indexed": true, 204 | "name": "from", 205 | "type": "address" 206 | }, 207 | { 208 | "indexed": true, 209 | "name": "to", 210 | "type": "address" 211 | }, 212 | { 213 | "indexed": false, 214 | "name": "value", 215 | "type": "uint256" 216 | } 217 | ], 218 | "name": "Transfer", 219 | "type": "event" 220 | } 221 | ] 222 | -------------------------------------------------------------------------------- /eth/abis/WalletFactory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_implementationAddress", 7 | "type": "address" 8 | } 9 | ], 10 | "stateMutability": "nonpayable", 11 | "type": "constructor" 12 | }, 13 | { 14 | "anonymous": false, 15 | "inputs": [ 16 | { 17 | "indexed": false, 18 | "internalType": "address", 19 | "name": "newWalletAddress", 20 | "type": "address" 21 | } 22 | ], 23 | "name": "WalletCreated", 24 | "type": "event" 25 | }, 26 | { 27 | "inputs": [], 28 | "name": "implementationAddress", 29 | "outputs": [ 30 | { 31 | "internalType": "address", 32 | "name": "", 33 | "type": "address" 34 | } 35 | ], 36 | "stateMutability": "view", 37 | "type": "function" 38 | }, 39 | { 40 | "inputs": [ 41 | { 42 | "internalType": "address[]", 43 | "name": "allowedSigners", 44 | "type": "address[]" 45 | }, 46 | { 47 | "internalType": "bytes32", 48 | "name": "salt", 49 | "type": "bytes32" 50 | } 51 | ], 52 | "name": "createWallet", 53 | "outputs": [], 54 | "stateMutability": "nonpayable", 55 | "type": "function" 56 | } 57 | ] 58 | -------------------------------------------------------------------------------- /eth/abis/WalletSimple.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "toAddress", 7 | "type": "address" 8 | }, 9 | { 10 | "name": "value", 11 | "type": "uint256" 12 | }, 13 | { 14 | "name": "tokenContractAddress", 15 | "type": "address" 16 | }, 17 | { 18 | "name": "expireTime", 19 | "type": "uint256" 20 | }, 21 | { 22 | "name": "sequenceId", 23 | "type": "uint256" 24 | }, 25 | { 26 | "name": "signature", 27 | "type": "bytes" 28 | } 29 | ], 30 | "name": "sendMultiSigToken", 31 | "outputs": [], 32 | "payable": false, 33 | "stateMutability": "nonpayable", 34 | "type": "function" 35 | }, 36 | { 37 | "constant": true, 38 | "inputs": [ 39 | { 40 | "name": "", 41 | "type": "uint256" 42 | } 43 | ], 44 | "name": "signers", 45 | "outputs": [ 46 | { 47 | "name": "", 48 | "type": "address" 49 | } 50 | ], 51 | "payable": false, 52 | "stateMutability": "view", 53 | "type": "function" 54 | }, 55 | { 56 | "constant": false, 57 | "inputs": [ 58 | { 59 | "name": "forwarderAddress", 60 | "type": "address" 61 | }, 62 | { 63 | "name": "tokenContractAddress", 64 | "type": "address" 65 | } 66 | ], 67 | "name": "flushForwarderTokens", 68 | "outputs": [], 69 | "payable": false, 70 | "stateMutability": "nonpayable", 71 | "type": "function" 72 | }, 73 | { 74 | "constant": false, 75 | "inputs": [ 76 | { 77 | "name": "toAddress", 78 | "type": "address" 79 | }, 80 | { 81 | "name": "value", 82 | "type": "uint256" 83 | }, 84 | { 85 | "name": "data", 86 | "type": "bytes" 87 | }, 88 | { 89 | "name": "expireTime", 90 | "type": "uint256" 91 | }, 92 | { 93 | "name": "sequenceId", 94 | "type": "uint256" 95 | }, 96 | { 97 | "name": "signature", 98 | "type": "bytes" 99 | } 100 | ], 101 | "name": "sendMultiSig", 102 | "outputs": [], 103 | "payable": false, 104 | "stateMutability": "nonpayable", 105 | "type": "function" 106 | }, 107 | { 108 | "constant": true, 109 | "inputs": [ 110 | { 111 | "name": "signer", 112 | "type": "address" 113 | } 114 | ], 115 | "name": "isSigner", 116 | "outputs": [ 117 | { 118 | "name": "", 119 | "type": "bool" 120 | } 121 | ], 122 | "payable": false, 123 | "stateMutability": "view", 124 | "type": "function" 125 | }, 126 | { 127 | "constant": true, 128 | "inputs": [], 129 | "name": "getNextSequenceId", 130 | "outputs": [ 131 | { 132 | "name": "", 133 | "type": "uint256" 134 | } 135 | ], 136 | "payable": false, 137 | "stateMutability": "view", 138 | "type": "function" 139 | }, 140 | { 141 | "constant": false, 142 | "inputs": [], 143 | "name": "createForwarder", 144 | "outputs": [ 145 | { 146 | "name": "", 147 | "type": "address" 148 | } 149 | ], 150 | "payable": false, 151 | "stateMutability": "nonpayable", 152 | "type": "function" 153 | }, 154 | { 155 | "constant": true, 156 | "inputs": [], 157 | "name": "safeMode", 158 | "outputs": [ 159 | { 160 | "name": "", 161 | "type": "bool" 162 | } 163 | ], 164 | "payable": false, 165 | "stateMutability": "view", 166 | "type": "function" 167 | }, 168 | { 169 | "constant": false, 170 | "inputs": [], 171 | "name": "activateSafeMode", 172 | "outputs": [], 173 | "payable": false, 174 | "stateMutability": "nonpayable", 175 | "type": "function" 176 | }, 177 | { 178 | "inputs": [ 179 | { 180 | "name": "allowedSigners", 181 | "type": "address[]" 182 | } 183 | ], 184 | "payable": false, 185 | "stateMutability": "nonpayable", 186 | "type": "constructor" 187 | }, 188 | { 189 | "payable": true, 190 | "stateMutability": "payable", 191 | "type": "fallback" 192 | }, 193 | { 194 | "anonymous": false, 195 | "inputs": [ 196 | { 197 | "indexed": false, 198 | "name": "from", 199 | "type": "address" 200 | }, 201 | { 202 | "indexed": false, 203 | "name": "value", 204 | "type": "uint256" 205 | }, 206 | { 207 | "indexed": false, 208 | "name": "data", 209 | "type": "bytes" 210 | } 211 | ], 212 | "name": "Deposited", 213 | "type": "event" 214 | }, 215 | { 216 | "anonymous": false, 217 | "inputs": [ 218 | { 219 | "indexed": false, 220 | "name": "msgSender", 221 | "type": "address" 222 | } 223 | ], 224 | "name": "SafeModeActivated", 225 | "type": "event" 226 | }, 227 | { 228 | "anonymous": false, 229 | "inputs": [ 230 | { 231 | "indexed": false, 232 | "name": "msgSender", 233 | "type": "address" 234 | }, 235 | { 236 | "indexed": false, 237 | "name": "otherSigner", 238 | "type": "address" 239 | }, 240 | { 241 | "indexed": false, 242 | "name": "operation", 243 | "type": "bytes32" 244 | }, 245 | { 246 | "indexed": false, 247 | "name": "toAddress", 248 | "type": "address" 249 | }, 250 | { 251 | "indexed": false, 252 | "name": "value", 253 | "type": "uint256" 254 | }, 255 | { 256 | "indexed": false, 257 | "name": "data", 258 | "type": "bytes" 259 | } 260 | ], 261 | "name": "Transacted", 262 | "type": "event" 263 | } 264 | ] 265 | -------------------------------------------------------------------------------- /eth/abis/WrappedTokenMembers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [{ "name": "merchant", "type": "address" }], 5 | "name": "removeMerchant", 6 | "outputs": [{ "name": "", "type": "bool" }], 7 | "payable": false, 8 | "stateMutability": "nonpayable", 9 | "type": "function" 10 | }, 11 | { 12 | "constant": false, 13 | "inputs": [{ "name": "_token", "type": "address" }], 14 | "name": "reclaimToken", 15 | "outputs": [], 16 | "payable": false, 17 | "stateMutability": "nonpayable", 18 | "type": "function" 19 | }, 20 | { 21 | "constant": true, 22 | "inputs": [{ "name": "addr", "type": "address" }], 23 | "name": "isMerchant", 24 | "outputs": [{ "name": "", "type": "bool" }], 25 | "payable": false, 26 | "stateMutability": "view", 27 | "type": "function" 28 | }, 29 | { 30 | "constant": true, 31 | "inputs": [{ "name": "addr", "type": "address" }], 32 | "name": "isCustodian", 33 | "outputs": [{ "name": "", "type": "bool" }], 34 | "payable": false, 35 | "stateMutability": "view", 36 | "type": "function" 37 | }, 38 | { 39 | "constant": true, 40 | "inputs": [], 41 | "name": "custodian", 42 | "outputs": [{ "name": "", "type": "address" }], 43 | "payable": false, 44 | "stateMutability": "view", 45 | "type": "function" 46 | }, 47 | { 48 | "constant": false, 49 | "inputs": [{ "name": "_custodian", "type": "address" }], 50 | "name": "setCustodian", 51 | "outputs": [{ "name": "", "type": "bool" }], 52 | "payable": false, 53 | "stateMutability": "nonpayable", 54 | "type": "function" 55 | }, 56 | { 57 | "constant": false, 58 | "inputs": [], 59 | "name": "claimOwnership", 60 | "outputs": [], 61 | "payable": false, 62 | "stateMutability": "nonpayable", 63 | "type": "function" 64 | }, 65 | { 66 | "constant": true, 67 | "inputs": [{ "name": "index", "type": "uint256" }], 68 | "name": "getMerchant", 69 | "outputs": [{ "name": "", "type": "address" }], 70 | "payable": false, 71 | "stateMutability": "view", 72 | "type": "function" 73 | }, 74 | { 75 | "constant": false, 76 | "inputs": [], 77 | "name": "renounceOwnership", 78 | "outputs": [], 79 | "payable": false, 80 | "stateMutability": "nonpayable", 81 | "type": "function" 82 | }, 83 | { 84 | "constant": true, 85 | "inputs": [], 86 | "name": "owner", 87 | "outputs": [{ "name": "", "type": "address" }], 88 | "payable": false, 89 | "stateMutability": "view", 90 | "type": "function" 91 | }, 92 | { 93 | "constant": false, 94 | "inputs": [{ "name": "merchant", "type": "address" }], 95 | "name": "addMerchant", 96 | "outputs": [{ "name": "", "type": "bool" }], 97 | "payable": false, 98 | "stateMutability": "nonpayable", 99 | "type": "function" 100 | }, 101 | { 102 | "constant": true, 103 | "inputs": [], 104 | "name": "getMerchants", 105 | "outputs": [{ "name": "", "type": "address[]" }], 106 | "payable": false, 107 | "stateMutability": "view", 108 | "type": "function" 109 | }, 110 | { 111 | "constant": true, 112 | "inputs": [], 113 | "name": "pendingOwner", 114 | "outputs": [{ "name": "", "type": "address" }], 115 | "payable": false, 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, 119 | { 120 | "constant": false, 121 | "inputs": [{ "name": "newOwner", "type": "address" }], 122 | "name": "transferOwnership", 123 | "outputs": [], 124 | "payable": false, 125 | "stateMutability": "nonpayable", 126 | "type": "function" 127 | }, 128 | { 129 | "inputs": [{ "name": "_owner", "type": "address" }], 130 | "payable": false, 131 | "stateMutability": "nonpayable", 132 | "type": "constructor" 133 | }, 134 | { 135 | "anonymous": false, 136 | "inputs": [{ "indexed": true, "name": "custodian", "type": "address" }], 137 | "name": "CustodianSet", 138 | "type": "event" 139 | }, 140 | { 141 | "anonymous": false, 142 | "inputs": [{ "indexed": true, "name": "merchant", "type": "address" }], 143 | "name": "MerchantAdd", 144 | "type": "event" 145 | }, 146 | { 147 | "anonymous": false, 148 | "inputs": [{ "indexed": true, "name": "merchant", "type": "address" }], 149 | "name": "MerchantRemove", 150 | "type": "event" 151 | }, 152 | { 153 | "anonymous": false, 154 | "inputs": [{ "indexed": true, "name": "previousOwner", "type": "address" }], 155 | "name": "OwnershipRenounced", 156 | "type": "event" 157 | }, 158 | { 159 | "anonymous": false, 160 | "inputs": [ 161 | { "indexed": true, "name": "previousOwner", "type": "address" }, 162 | { "indexed": true, "name": "newOwner", "type": "address" } 163 | ], 164 | "name": "OwnershipTransferred", 165 | "type": "event" 166 | } 167 | ] 168 | -------------------------------------------------------------------------------- /eth/abis/index.ts: -------------------------------------------------------------------------------- 1 | 2 | import Compound from './Compound.json'; 3 | import CompoundComptroller from './CompoundComptroller.json'; 4 | import DepositContract from './DepositContract.json'; 5 | import DSProxy from './DSProxy.json'; 6 | import DSProxyActions from './DSProxyActions.json'; 7 | import DSProxyActionsDsr from './DSProxyActionsDsr.json'; 8 | import DSProxyFactory from './DSProxyFactory.json'; 9 | import DsrManager from './DsrManager.json'; 10 | import Forwarder from './Forwarder.json'; 11 | import ForwarderFactory from './ForwarderFactory.json'; 12 | import SkaleAllocator from './SkaleAllocator.json'; 13 | import SkaleDelegationController from './SkaleDelegationController.json'; 14 | import SkaleEscrow from './SkaleEscrow.json'; 15 | import SkaleDistributor from './SkaleDistributor.json'; 16 | import SkaleTokenState from './SkaleTokenState.json'; 17 | import SkaleValidatorService from './SkaleValidatorService.json'; 18 | import StandardERC20 from './StandardERC20.json'; 19 | import WalletFactory from './WalletFactory.json'; 20 | import WalletSimple from './WalletSimple.json'; 21 | import WrappedToken from './WrappedToken.json'; 22 | import WrappedTokenController from './WrappedTokenController.json'; 23 | import WrappedTokenFactory from './WrappedTokenFactory.json'; 24 | import WrappedTokenMembers from './WrappedTokenMembers.json'; 25 | import UniswapV2SwapRouter from './UniswapV2SwapRouter.json'; 26 | import UniswapV3SwapRouter from './UniswapV3SwapRouter.json'; 27 | import UniswapV3NonfungiblePositionManager from './UniswapV3NonfungiblePositionManager.json'; 28 | import SushiswapV2Router from './SushiswapV2Router.json'; 29 | import KashiPairMediumRiskV1 from './KashiPairMediumRiskV1.json'; 30 | import WrappedTokenControllerV1 from './WrappedTokenControllerV1.json' 31 | import WrappedTokenFactoryV1 from './WrappedTokenFactoryV1.json' 32 | export default { 33 | Compound, 34 | CompoundComptroller, 35 | DepositContract, 36 | DSProxy, 37 | DSProxyActions, 38 | DSProxyActionsDsr, 39 | DSProxyFactory, 40 | DsrManager, 41 | Forwarder, 42 | ForwarderFactory, 43 | SkaleAllocator, 44 | SkaleDelegationController, 45 | SkaleEscrow, 46 | SkaleDistributor, 47 | SkaleTokenState, 48 | SkaleValidatorService, 49 | StandardERC20, 50 | WalletFactory, 51 | WalletSimple, 52 | UniswapV2SwapRouter, 53 | UniswapV3SwapRouter, 54 | UniswapV3NonfungiblePositionManager, 55 | SushiswapV2Router, 56 | KashiPairMediumRiskV1, 57 | WrappedToken, 58 | WrappedTokenController, 59 | WrappedTokenFactory, 60 | WrappedTokenMembers, 61 | WrappedTokenControllerV1, 62 | WrappedTokenFactoryV1, 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /eth/config/instances.json: -------------------------------------------------------------------------------- 1 | { 2 | "StandardERC20": { 3 | "WXRP": "0xda7e5a3841550a5ba271dcc76a885af902142dfc", 4 | "OMG": "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", 5 | "REP": "0x1985365e9f78359a9b6ad760e32412f4a445e862", 6 | "GNT": "0xda7e5a3841550a5ba271dcc76a885af902142dfc", 7 | "BAT": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", 8 | "ZRX": "0xe41d2489571d322189246dafa5ebde1f4699f498", 9 | "KNC": "0xdd974d5c2e2928dea5f71b9825b8b646686bd200", 10 | "USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", 11 | "DAI": "0x6B175474E89094C44Da98b954EedeAC495271d0F", 12 | "SAI": "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359", 13 | "UNI": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", 14 | "USDT": "0xdac17f958d2ee523a2206206994597c13d831ec7" 15 | }, 16 | "WrappedToken": { 17 | "WBTC": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", 18 | "WDOGE": "0x8aa9381b2544b48c26f3b850F6e07E2c5161EB3e" 19 | }, 20 | "WrappedTokenFactory":{ 21 | "WBTC": "0xe5a5f138005e19a3e6d0fe68b039397eeef2322b" 22 | }, 23 | "WrappedTokenController":{ 24 | "WBTC": "0xCA06411bd7a7296d7dbdd0050DFc846E95fEBEB7" 25 | }, 26 | "WrappedTokenMembers":{ 27 | "WBTC": "0x3e8640574aa764763291eD733672D3A105107ac5", 28 | "WDOGE": "0x78749C8E1af46cA85bEE4AE566F0Fe9a324ac531" 29 | }, 30 | "WrappedTokenFactoryV1":{ 31 | "WDOGE": "0x62084120c6006956dDa975B89C07b7d68b6D61E0" 32 | }, 33 | "WrappedTokenControllerV1":{ 34 | "WDOGE": "0xaF9f0d1CE262d70be64346cBa74706230951f067" 35 | }, 36 | "Compound": { 37 | "CUSDC": "0x39aa39c021dfbae8fac545936693ac917d5e7563", 38 | "CBAT": "0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e", 39 | "CDAI": "0x5d3a536e4d6dbd6114cc1ead35777bab948e3643", 40 | "CETH": "0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5", 41 | "CREP": "0x158079ee67fce2f58472a96584a73c7ab9ac95c1", 42 | "CSAI": "0xf5dce57282a584d2746faf1593d3121fcac444dc", 43 | "CWBTC": "0xc11b1268c1a384e55c48c2391d8d480264a3a7f4", 44 | "CZRX": "0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407" 45 | }, 46 | "CompoundComptroller": { 47 | "default": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B" 48 | }, 49 | "DSProxyFactory": { 50 | "default": "0x4678f0a6958e4d2bc4f1baf7bc52e8f3564f3fe4" 51 | }, 52 | "DSProxyActionsDsr": { 53 | "default": "0x07ee93aeea0a36fff2a9b95dd22bd6049ee54f26" 54 | }, 55 | "DSProxyActions": { 56 | "default": "0x82ecd135dce65fbc6dbdd0e4237e0af93ffd5038" 57 | }, 58 | "DsrManager": { 59 | "default": "0x373238337Bfe1146fb49989fc222523f83081dDb" 60 | }, 61 | "DSProxy": { 62 | }, 63 | "SkaleDelegationController": { 64 | "default": "0x06dD71dAb27C1A3e0B172d53735f00Bf1a66Eb79" 65 | }, 66 | "SkaleDistributor": { 67 | "default": "0x2a42Ccca55FdE8a9CA2D7f3C66fcddE99B4baB90" 68 | }, 69 | "SkaleAllocator": { 70 | "default": "0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba" 71 | }, 72 | "SkaleTokenState": { 73 | "default": "0x1F2157Bf5C820f68826ef1DC71824816Ee795f41" 74 | }, 75 | "SkaleEscrow": { 76 | }, 77 | "SkaleValidatorService": { 78 | "default": "0x840C8122433A5AA7ad60C1Bcdc36AB9DcCF761a5" 79 | }, 80 | "DepositContract": { 81 | }, 82 | "Forwarder": { 83 | }, 84 | "WalletSimple": { 85 | }, 86 | "ForwarderFactory": { 87 | }, 88 | "WalletFactory": { 89 | }, 90 | "UniswapV2SwapRouter": { 91 | "default": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d" 92 | }, 93 | "UniswapV3SwapRouter": { 94 | "default": "0xe592427a0aece92de3edee1f18e0157c05861564" 95 | }, 96 | "UniswapV3NonfungiblePositionManager":{ 97 | "default": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88" 98 | }, 99 | "SushiswapV2Router":{ 100 | "default": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" 101 | }, 102 | "KashiPairMediumRiskV1":{ 103 | "default": "0x2cBA6Ab6574646Badc84F0544d05059e57a5dc42" 104 | 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /eth/examples/Compound/borrow.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | /* 4 | * Note that to borrow, you must have a certain amount of assets lent to the compound protocol. 5 | * You must also explicitly enable those assets to be used as collateral 6 | */ 7 | 8 | const collateralTokenName = 'cDAI'; 9 | const borrowTokenName = 'USDC'; 10 | const compoundTokenName = 'cUSDC'; 11 | const borrowAmount = 1e5; 12 | 13 | const compoundComptroller = getContractsFactory('eth').getContract('CompoundComptroller').instance(); 14 | const compoundCollateralTokenContract = getContractsFactory('eth').getContract('Compound').instance(collateralTokenName); 15 | 16 | // First we need to "enter the market" for our collateral token. This assumes that we already have some cTokens to use 17 | let { data, amount } = compoundComptroller.methods() 18 | .enterMarkets.call({ cTokens: [compoundCollateralTokenContract.address] }); 19 | 20 | console.log(`\nTo enter ${collateralTokenName} as collateral for borrowing, send:`); 21 | console.log(`Data: ${data}`); 22 | console.log(`Amount: ${amount} ETH`); 23 | console.log(`To: ${compoundComptroller.address}`); 24 | 25 | // Once the above tx is confirmed, we can borrow our desired underlying asset 26 | const compoundTokenContract = getContractsFactory('eth').getContract('Compound').instance(compoundTokenName); 27 | 28 | ({ data, amount } = compoundTokenContract.methods() 29 | .borrow.call({ borrowAmount: borrowAmount.toString(10) })); 30 | 31 | console.log(`\nTo borrow ${borrowAmount} ${borrowTokenName} from compound, send:`); 32 | console.log(`Data: ${data}`); 33 | console.log(`Amount: ${amount} ETH`); 34 | console.log(`To: ${compoundTokenContract.address}`); 35 | -------------------------------------------------------------------------------- /eth/examples/Compound/lend.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const underlyingTokenName = 'DAI'; 4 | const compoundTokenName = 'cDAI'; 5 | const lendAmount = 1e18; // 1 DAI 6 | 7 | const underlyingTokenContract = getContractsFactory('eth').getContract('StandardERC20').instance(underlyingTokenName); 8 | const compoundTokenContract = getContractsFactory('eth').getContract('Compound').instance(compoundTokenName); 9 | 10 | // First we need to approve the amount of DAI for the compound DAI contract to control 11 | let { data, amount } = underlyingTokenContract.methods().approve.call( 12 | { 13 | _spender: compoundTokenContract.address, 14 | _value: lendAmount.toString(10), 15 | }); 16 | 17 | console.log(`To approve ${lendAmount} ${underlyingTokenName} to compound token contract, send:`); 18 | console.log(`Data: ${data}`); 19 | console.log(`Amount: ${amount} ETH`); 20 | console.log(`To: ${underlyingTokenContract.address}`); 21 | 22 | 23 | // Then, once the above tx is confirmed, we can mint our new cTokens 24 | ({ data, amount } = compoundTokenContract.methods().mint.call({ mintAmount: lendAmount.toString(10) })); 25 | 26 | console.log(`\nTo exchange ${lendAmount} ${underlyingTokenName} for compound tokens, send:`); 27 | console.log(`Data: ${data}`); 28 | console.log(`Amount: ${amount} ETH`); 29 | console.log(`To: ${compoundTokenContract.address}`); 30 | -------------------------------------------------------------------------------- /eth/examples/Compound/redeemLend.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const compoundTokenName = 'cDAI'; 4 | const redeemAmount = 49e8; // 49 cDAI 5 | 6 | const compoundTokenContract = getContractsFactory('eth').getContract('Compound').instance(compoundTokenName); 7 | 8 | const { data, amount } = compoundTokenContract.methods().redeem.call({ redeemTokens: redeemAmount.toString(10) }); 9 | 10 | console.log(`To redeem ${redeemAmount} ${compoundTokenName} compound tokens, send:`); 11 | console.log(`Data: ${data}`); 12 | console.log(`Amount: ${amount} ETH`); 13 | console.log(`To: ${compoundTokenContract.address}`); 14 | -------------------------------------------------------------------------------- /eth/examples/Compound/repayBorrow.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const repayTokenName = 'USDC'; 4 | const compoundTokenName = 'cUSDC'; 5 | const repayAmount = 1e5; // 0.1 USDC 6 | 7 | const underlyingTokenContract = getContractsFactory('eth').getContract('StandardERC20').instance(repayTokenName); 8 | const compoundTokenContract = getContractsFactory('eth').getContract('Compound').instance(compoundTokenName); 9 | 10 | // First we need to approve the amount of DAI for the compound DAI contract to control 11 | let { data, amount, address } = underlyingTokenContract.methods().approve.call( 12 | { 13 | _spender: compoundTokenContract.address, 14 | _value: repayAmount.toString(10), 15 | }); 16 | 17 | console.log(`To approve ${repayAmount} ${repayTokenName} to compound token contract, send:`); 18 | console.log(`Data: ${data}`); 19 | console.log(`Amount: ${amount} ETH`); 20 | console.log(`To: ${address}`); 21 | 22 | // Then we can tell the compound contract that we want to repay 23 | ({ data, amount, address } = compoundTokenContract.methods().repayBorrow.call({ repayAmount: repayAmount.toString(10) })); 24 | 25 | console.log(`\nTo repay ${repayAmount} ${repayTokenName} from compound, send:`); 26 | console.log(`Data: ${data}`); 27 | console.log(`Amount: ${amount} ETH`); 28 | console.log(`To: ${compoundTokenContract.address}`); 29 | -------------------------------------------------------------------------------- /eth/examples/DepositContract/deposit.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const depositContractAddress = '0x'; // this is not yet known 4 | const validatorKey = '0x0000'; 5 | const withdrawalKey = '0x0000'; 6 | const signature = '0x0000'; 7 | const depositDataRoot = '0x0000'; 8 | 9 | const depositContract = getContractsFactory('eth').getContract('DepositContract').instance(); 10 | depositContract.address = depositContractAddress; 11 | const { data, amount } = depositContract.methods() 12 | .deposit.call({ pubkey: validatorKey, withdrawal_credentials: withdrawalKey, signature: signature, deposit_data_root: depositDataRoot }); 13 | 14 | console.log(`\nTo deposit into the ETH2.0 deposit contract with validator key ${validatorKey}, withdrawalKey: ${withdrawalKey}, signature: ${signature}, depositDataRoot: ${depositDataRoot}, send:`); 15 | console.log(`Data: ${data}`); 16 | console.log(`Amount: ${amount} ETH`); 17 | console.log(`To: ${depositContract.address}`); 18 | -------------------------------------------------------------------------------- /eth/examples/MakerDAO/closeCDP.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import * as ethUtil from 'ethereumjs-util'; 3 | import { getContractsFactory } from '../../../src/index'; 4 | 5 | const daiToken = getContractsFactory('eth').getContract('StandardERC20').instance('dai'); 6 | 7 | async function sendBitGoTx(): Promise { 8 | /* 9 | * This assume you already have a CDP at Maker from our example createCDP 10 | * It also assume you already have a CDP setup 11 | * step 1 - Approve the number of tokens you would like the proxy to access 12 | */ 13 | 14 | const bitGo = new BitGo({ env: 'prod' }); 15 | const baseCoin = bitGo.coin('eth'); 16 | const depositAmount = 5e18; // The amount of dai you want to deposit. 17 | const withdrawAmount = 1e17; // The amount of eth you want to withdraw. 18 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 19 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 20 | const walletPassphrase = 'password'; 21 | 22 | // your proxy 23 | const proxyAddress = '0x17458bbdd96d6c19645457f5fae87ed5a07ad8fd'; 24 | const daiSavingsRateProxy = getContractsFactory('eth').getContract('DSProxy').instance(); 25 | daiSavingsRateProxy.address = proxyAddress; 26 | 27 | let { data, amount } = daiToken.methods().approve.call( 28 | { 29 | _spender: proxyAddress, 30 | _value: depositAmount.toString(10), 31 | }); 32 | 33 | let transaction = await bitGoWallet.send({ data, amount, address: daiToken.address, walletPassphrase }); 34 | console.dir(transaction); 35 | 36 | // Note this step only needs to be done once based on the amount you approve 37 | 38 | /* 39 | * ============================================ // 40 | * ============================================ // 41 | */ 42 | 43 | // step 2 - Deposit Dai and withdraw ETH 44 | 45 | /* 46 | * Now we need to go get the cdp id of the cdp that you created. The easiest way to do this is go to 47 | * the Etherscan page for the Dai manager contract, here: https://etherscan.io/address/0x5ef30b9986345249bc32d8928b7ee64de9435e39#readContract 48 | * Enter your proxy address in the 'last' query, then press `Query`. It will return your cdpid 49 | */ 50 | const cdp = '1913'; 51 | 52 | // The following two addresses are constants in the MakerDAO MCD ecosystem. You can look them up and verify on Etherscan 53 | const daiJoin = '0x9759a6ac90977b93b58547b4a71c78317f391a28'; 54 | const ethJoin = '0x2f0b23f53734252bda2277357e97e1517d6b042a'; 55 | const manager = '0x5ef30b9986345249bc32d8928b7ee64de9435e39'; 56 | 57 | const dsProxyActionsContract = getContractsFactory('eth').getContract('DSProxyActions').instance(); 58 | 59 | const { data: internalData, address: proxyActionsAddress } = dsProxyActionsContract.methods() 60 | .wipeAndFreeETH.call({ manager, ethJoin, daiJoin, cdp, wadC: withdrawAmount.toString(10), wadD: depositAmount.toString(10) }); 61 | 62 | // Build the external call for our proxy to deposit dai and withdaw eth 63 | ({ data, amount } = daiSavingsRateProxy.methods() 64 | .execute.call({ 65 | _target: proxyActionsAddress, 66 | _data: ethUtil.toBuffer(internalData), 67 | })); 68 | // send the transaction through BitGo 69 | 70 | transaction = await bitGoWallet.send({ 71 | data, 72 | address: daiSavingsRateProxy.address, 73 | amount, 74 | walletPassphrase, 75 | }); 76 | 77 | console.dir(transaction); 78 | } 79 | 80 | sendBitGoTx(); 81 | -------------------------------------------------------------------------------- /eth/examples/MakerDAO/createCDP.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import * as ethUtil from 'ethereumjs-util'; 3 | import { getContractsFactory } from '../../../src/index'; 4 | 5 | const makerProxyRegistry = getContractsFactory('eth').getContract('DSProxyFactory').instance(); 6 | 7 | async function sendBitGoTx(): Promise { 8 | // step 1 - setup your bitgo wallet and deploy your proxy 9 | 10 | const bitGo = new BitGo({ env: 'prod' }); 11 | const baseCoin = bitGo.coin('eth'); 12 | const withdrawAmount = 30 * 1e18; // The amount of dai you want to withdraw (more than $30). 13 | const depositAmount = 1e18; // Amount of eth you want to deposit 14 | bitGo.authenticateWithAccessToken({ accessToken: 'access token here' }); 15 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id here' }); 16 | const walletPassphrase = 'password'; 17 | 18 | 19 | /* 20 | * First we need to deploy a proxy contract that will simplify adding our DAI to the DSR 21 | * Note this step only needs to be done once per wallet, so if you have already done it, skip to the next step 22 | */ 23 | 24 | let { data, amount } = makerProxyRegistry.methods().build.call({}); 25 | let transaction = await bitGoWallet.send({ data, amount, address: makerProxyRegistry.address, walletPassphrase }); 26 | console.dir(transaction); 27 | 28 | /* 29 | * ============================================ // 30 | * ============================================ // 31 | */ 32 | 33 | // step 2 - Create CDP and withdraw DAI 34 | 35 | /* 36 | * Now we need to go get the address of the newly created proxy contract. The easiest way to do this is go to 37 | * the Etherscan page for the Proxy Registry contract, here: https://etherscan.io/address/0x4678f0a6958e4d2bc4f1baf7bc52e8f3564f3fe4#readContract 38 | * Enter your wallet address in the `proxies` query, then press `Query`. It will return your proxy address 39 | */ 40 | 41 | const proxyAddress = '0x17458bbdd96d6c19645457f5fae87ed5a07ad8fd'; 42 | 43 | const daiSavingsRateProxy = getContractsFactory('eth').getContract('DSProxy').instance(); 44 | daiSavingsRateProxy.address = proxyAddress; 45 | 46 | // The following addresses are constants in the MakerDAO MCD ecosystem. You can look them up and verify on Etherscan 47 | const daiJoin = '0x9759a6ac90977b93b58547b4a71c78317f391a28'; 48 | const ethJoin = '0x2f0b23f53734252bda2277357e97e1517d6b042a'; 49 | const manager = '0x5ef30b9986345249bc32d8928b7ee64de9435e39'; 50 | const jug = '0x19c0976f590d67707e62397c87829d896dc0f1f1'; 51 | 52 | const ilk = new Buffer('4554482d41000000000000000000000000000000000000000000000000000000', 'hex'); 53 | const dsProxyActionsContract = getContractsFactory('eth').getContract('DSProxyActions').instance(); 54 | 55 | const { data: internalData } = dsProxyActionsContract.methods() 56 | .openLockETHAndDraw.call({ manager, jug, ethJoin, daiJoin, ilk, wadD: withdrawAmount.toString(10) }); 57 | const proxyActionsAddress = dsProxyActionsContract.address; 58 | // Build the external call for our proxy to create the cdp 59 | ({ data, amount } = daiSavingsRateProxy.methods() 60 | .execute.call({ 61 | _target: proxyActionsAddress, 62 | _data: ethUtil.toBuffer(internalData), 63 | })); 64 | 65 | // send the transaction through BitGo 66 | transaction = await bitGoWallet.send({ 67 | data, 68 | address: daiSavingsRateProxy.address, 69 | amount: depositAmount.toString(10), 70 | walletPassphrase, 71 | }); 72 | 73 | console.dir(transaction); 74 | } 75 | 76 | 77 | sendBitGoTx(); 78 | -------------------------------------------------------------------------------- /eth/examples/MakerDAO/depositSavingsRate.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const daiToken = getContractsFactory('eth').getContract('StandardERC20').instance('dai'); 4 | const dsrManager = getContractsFactory('eth').getContract('DsrManager').instance(); 5 | 6 | // TODO: Set your own address here -- this is the address who can withdraw DAI from the DSR 7 | const ownerAddress = '0x0000000000000000000000000000000000000000'; 8 | // TODO: Set the desired amount of DAI to deposit in base units, so 1e18 is 1 DAI 9 | const depositAmount = 1e18; 10 | 11 | /* 12 | * ============================================ // 13 | * ============================================ // 14 | */ 15 | 16 | // First We need to approve ownership of some of our DAI to the DSR Manager 17 | 18 | let { data, amount } = daiToken.methods() 19 | .approve.call({ 20 | _spender: dsrManager.address, 21 | _value: depositAmount.toString(10), 22 | }); 23 | 24 | console.log(`\nTo approve ${depositAmount} DAI base units to the DSR Manager, send:`); 25 | console.log(`Data: ${data}`); 26 | console.log(`Amount: ${amount} ETH`); 27 | console.log(`To: ${daiToken.address}`); 28 | 29 | 30 | /* 31 | * ============================================ // 32 | * ============================================ // 33 | */ 34 | 35 | 36 | // Now we can actually deposit it and get the DSR 37 | 38 | ({ data, amount } = dsrManager.methods() 39 | .join.call({ 40 | dst: ownerAddress, 41 | wad: depositAmount.toString(10), 42 | })); 43 | 44 | console.log(`\nTo deposit ${depositAmount} DAI base units into the DSR`); 45 | console.log(`Data: ${data}`); 46 | console.log(`Amount: ${amount} ETH`); 47 | console.log(`To: ${dsrManager.address}`); 48 | -------------------------------------------------------------------------------- /eth/examples/MakerDAO/withdrawSavingsRate.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const dsrManager = getContractsFactory('eth').getContract('DsrManager').instance(); 4 | 5 | // TODO: Set your own address here -- this is the address who can withdraw DAI from the DSR 6 | const ownerAddress = '0x0000000000000000000000000000000000000000'; 7 | 8 | /* 9 | * ============================================ // 10 | * ============================================ // 11 | */ 12 | 13 | // Withdraw all DAI From the DSR 14 | 15 | const { data, amount } = dsrManager.methods() 16 | .exitAll.call({ 17 | dst: ownerAddress, 18 | }); 19 | 20 | console.log(`\nTo withdraw all DAI from the DSR`); 21 | console.log(`Data: ${data}`); 22 | console.log(`Amount: ${amount} ETH`); 23 | console.log(`To: ${dsrManager.address}`); 24 | -------------------------------------------------------------------------------- /eth/examples/SKALE/bountiesEarned.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0x2a42Ccca55FdE8a9CA2D7f3C66fcddE99B4baB90'; 14 | const Distributor = getContractsFactory('eth').getContract('SkaleDistributor').instance(); 15 | Distributor.address = proxyAddress; 16 | 17 | //parameter needed for checking the earned bounties 18 | const idOfValidator = 'validator id'; 19 | 20 | /** 21 | * Retrieve the amount of earned bounties for the provided by token holder (delgator). 22 | * This will return the bounties earned since the last withdraw for a specific delegation to a validator. 23 | * This needs to be called for each validator that a token holder (delegator) is delegating to. 24 | */ 25 | const { data, amount } = Distributor.methods().getAndUpdateEarnedBountyAmount.call({ 26 | validatorId: idOfValidator, 27 | }); 28 | console.log({ data, amount, to: Distributor.address }); 29 | 30 | 31 | const transaction = await bitGoWallet.send({ data, amount, address: Distributor.address, walletPassphrase }); 32 | console.dir(transaction); 33 | 34 | } 35 | 36 | sendBitGoTx(); 37 | -------------------------------------------------------------------------------- /eth/examples/SKALE/cancelPendingDelegation.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | //parameter needed for cancel delegation request 14 | const idOfDelegation = 'ID of delegation to cancel'; 15 | 16 | const proxyAddress = '0x06dD71dAb27C1A3e0B172d53735f00Bf1a66Eb79'; 17 | const DelegationController = getContractsFactory('eth').getContract('SkaleDelegationController').instance(); 18 | DelegationController.address = proxyAddress; 19 | 20 | /** 21 | * This allows the delegator to cancel the PENDING delegation before the validator approves 22 | * or before the start of the next Epoch. 23 | * If a delegation is already in the DELEGATED or COMPLETED state, this method can not be called. 24 | */ 25 | const { data, amount } = DelegationController.methods().cancelPendingDelegation.call({ 26 | delegationId: idOfDelegation, 27 | }); 28 | const transaction = await bitGoWallet.send({ data, amount, address: DelegationController.address, walletPassphrase }); 29 | console.dir(transaction); 30 | 31 | } 32 | 33 | sendBitGoTx(); 34 | -------------------------------------------------------------------------------- /eth/examples/SKALE/cancelPendingDelegationFromEscrow.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 14 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 15 | Allocator.address = proxyAddress; 16 | 17 | /** 18 | * Get the Escrow wallet address that is linked to the delegator's Bitgo wallet address 19 | */ 20 | let { data, amount } = Allocator.methods().getEscrowAddress.call({ 21 | beneficiary: bitGoWallet.getAddress(), 22 | }); 23 | const escrowAddress = await bitGoWallet.send({ data, amount, address: Allocator.address, walletPassphrase }); 24 | 25 | //Retrieve Escrow contract for delegator 26 | const Escrow = getContractsFactory('eth').getContract('SkaleEscrow').instance(); 27 | Escrow.address = escrowAddress; 28 | 29 | //parameter needed for cancel delegation request 30 | const idOfDelegation = 'ID of delegation to cancel'; 31 | 32 | 33 | /** 34 | * Request to cancel PENDING delegation from the delegator's Escrow account. 35 | * 36 | * This allows the delegator to cancel the PENDING delegation before the validator approves 37 | * or before the start of the next Epoch. 38 | * If a delegation is already in the DELEGATED or COMPLETED state, this method can not be called. 39 | */ 40 | ({ data, amount } = Escrow.methods().cancelPendingDelegation.call({ 41 | delegationId: idOfDelegation, 42 | })); 43 | const transaction = await bitGoWallet.send({ data, amount, address: Escrow.address, walletPassphrase }); 44 | console.dir(transaction); 45 | 46 | 47 | } 48 | 49 | sendBitGoTx(); 50 | -------------------------------------------------------------------------------- /eth/examples/SKALE/delegate.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | //parameters needed for the delegation request 14 | const idOfValidator = 'validator id'; 15 | const amounttoDelegate = 'amount of proposed delegation'; 16 | const proposedDelegationPeriod = 'period of proposed delegation (3months)'; 17 | const descriptionAboutDelegation = 'description or summary about the delegation'; 18 | 19 | const proxyAddress = '0x06dD71dAb27C1A3e0B172d53735f00Bf1a66Eb79'; 20 | const DelegationController = getContractsFactory('eth').getContract('SkaleDelegationController').instance(); 21 | DelegationController.address = proxyAddress; 22 | 23 | /** 24 | * Sending a proposal to delegate SKL tokens to the validator. 25 | */ 26 | const { data, amount } = DelegationController.methods().delegate.call({ 27 | validatorId: idOfValidator, 28 | amount: amounttoDelegate, 29 | delegationPeriod: proposedDelegationPeriod, 30 | info: descriptionAboutDelegation, 31 | }); 32 | const transaction = await bitGoWallet.send({ data, amount, address: DelegationController.address, walletPassphrase }); 33 | console.dir(transaction); 34 | 35 | } 36 | 37 | sendBitGoTx(); 38 | -------------------------------------------------------------------------------- /eth/examples/SKALE/delegateFromEscrow.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 14 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 15 | Allocator.address = proxyAddress; 16 | 17 | /** 18 | * Get the Escrow wallet address that is linked to the delegator's Bitgo wallet address 19 | */ 20 | let { data, amount } = Allocator.methods().getEscrowAddress.call({ 21 | beneficiary: bitGoWallet.getAddress(), 22 | }); 23 | const escrowAddress = await bitGoWallet.send({ data, amount, address: Allocator.address, walletPassphrase }); 24 | 25 | //Retrieve Escrow contract for delegator 26 | const Escrow = getContractsFactory('eth').getContract('SkaleEscrow').instance(); 27 | Escrow.address = escrowAddress; 28 | 29 | //parameters needed for the delegation request 30 | const idOfValidator = 'validator id'; 31 | const amounttoDelegate = 'amount of proposed delegation'; 32 | const proposedDelegationPeriod = 'period of proposed delegation (3months)'; 33 | const descriptionAboutDelegation = 'description or summary about the delegation'; 34 | 35 | 36 | /** 37 | * Sending a proposal to delegate SKL tokens to the validator from the delegator's Escrow account. 38 | */ 39 | ({ data, amount } = Escrow.methods().delegate.call({ 40 | validatorId: idOfValidator, 41 | amount: amounttoDelegate, 42 | delegationPeriod: proposedDelegationPeriod, 43 | info: descriptionAboutDelegation, 44 | })); 45 | const transaction = await bitGoWallet.send({ data, amount, address: Escrow.address, walletPassphrase }); 46 | console.dir(transaction); 47 | 48 | 49 | } 50 | 51 | sendBitGoTx(); 52 | -------------------------------------------------------------------------------- /eth/examples/SKALE/getEscrowAddress.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | 12 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 13 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 14 | Allocator.address = proxyAddress; 15 | 16 | /** 17 | * Get the Escrow wallet address that is linked to the investor's Bitgo wallet address 18 | */ 19 | const { data, amount } = Allocator.methods().getEscrowAddress.call({ 20 | beneficiary: bitGoWallet.getAddress(), 21 | }); 22 | const address = Allocator.address; 23 | console.log(data, amount, address); 24 | 25 | } 26 | 27 | sendBitGoTx(); 28 | -------------------------------------------------------------------------------- /eth/examples/SKALE/listDelegation.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | 12 | const proxyAddress = '0x06dD71dAb27C1A3e0B172d53735f00Bf1a66Eb79'; 13 | const DelegationController = getContractsFactory('eth').getContract('SkaleDelegationController').instance(); 14 | DelegationController.address = proxyAddress; 15 | 16 | const delegations = []; 17 | /** 18 | * List all of the delegations for th token holder (delegator). 19 | * This will return the states of each of the delegation requests sent. 20 | * 21 | * First get Total amount of delegations for the holder 22 | */ 23 | let { data, amount } = DelegationController.methods().getDelegationsByHolderLength.call({ 24 | holder: bitGoWallet.getAddress(), 25 | }); 26 | 27 | /** 28 | * Then get the delegation ids for the total amount of delegations. 29 | */ 30 | for (let index = 0; index < parseInt(data, 10); index++) { 31 | const delegation = { info: {}, state: {} }; 32 | 33 | const delegationId = ({ data, amount } = DelegationController.methods().delegationsByHolder.call({ 34 | address: bitGoWallet.getAddress(), 35 | index: index, 36 | })); 37 | 38 | const delegationInfo = ({ data, amount } = DelegationController.methods().getDelegation.call({ 39 | delegationId: delegationId, 40 | })); 41 | 42 | /** 43 | * Get the state of the delegation (PROPOSED, ACCEPTED, CANCELED, etc). State is returned as an integer 44 | * where 0 = PROPOSED, 1 = ACCEPTED, etc 45 | * States can be found below 46 | * //https://github.com/skalenetwork/skale-manager/blob/develop/contracts/delegation/DelegationController.sol#L64 47 | */ 48 | const delegationState = ({ data } = DelegationController.methods().getState.call({ 49 | delegationId: delegationId, 50 | })); 51 | 52 | delegation.info = delegationInfo.data; 53 | delegation.state = delegationState.data; 54 | 55 | delegations.push(delegation); 56 | } 57 | const address = DelegationController.address; 58 | console.log(data, amount, address); 59 | 60 | } 61 | 62 | sendBitGoTx(); 63 | -------------------------------------------------------------------------------- /eth/examples/SKALE/listDelegationFromEscrow.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 14 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 15 | Allocator.address = proxyAddress; 16 | 17 | /** 18 | * Get the Escrow wallet address that is linked to the delegator's Bitgo wallet address 19 | */ 20 | let { data, amount } = Allocator.methods().getEscrowAddress.call({ 21 | beneficiary: bitGoWallet.getAddress(), 22 | }); 23 | const escrowAddress = await bitGoWallet.send({ data, amount, address: Allocator.address, walletPassphrase }); 24 | 25 | const delegationControllerAddress = '0x06dD71dAb27C1A3e0B172d53735f00Bf1a66Eb79'; 26 | const DelegationController = getContractsFactory('eth').getContract('SkaleDelegationController').instance(); 27 | DelegationController.address = delegationControllerAddress; 28 | const delegations = []; 29 | /** 30 | * List all of the delegations for th token holder's Escrow contract. 31 | * This will return the states of each of the delegation requests sent. 32 | * 33 | * First get Total amount of delegations for the holder 34 | */ 35 | const delegationsTotal = ({ data, amount } = DelegationController.methods().getDelegationsByHolderLength.call({ 36 | holder: escrowAddress, 37 | })); 38 | 39 | /** 40 | * Then get the delegation ids for the total amount of delegations. 41 | */ 42 | for (let index = 0; index < parseInt(delegationsTotal.data, 10); index++) { 43 | const delegation = { info: {}, state: {} }; 44 | 45 | const delegationId = ({ data, amount } = DelegationController.methods().delegationsByHolder.call({ 46 | address: escrowAddress, 47 | index: index, 48 | })); 49 | 50 | const delegationInfo = ({ data, amount } = DelegationController.methods().getDelegation.call({ 51 | delegationId: delegationId, 52 | })); 53 | 54 | /** 55 | * Get the state of the delegation (PROPOSED, ACCEPTED, CANCELED, etc). State is returned as an integer 56 | * where 0 = PROPOSED, 1 = ACCEPTED, etc 57 | * States can be found below 58 | * //https://github.com/skalenetwork/skale-manager/blob/develop/contracts/delegation/DelegationController.sol#L64 59 | */ 60 | const delegationState = ({ data, amount } = DelegationController.methods().getState.call({ 61 | delegationId: delegationId, 62 | })); 63 | 64 | delegation.info = delegationInfo.data; 65 | delegation.state = delegationState.data; 66 | 67 | delegations.push(delegation); 68 | } 69 | const transaction = await bitGoWallet.send({ data, amount, address: DelegationController.address, walletPassphrase }); 70 | console.dir(transaction); 71 | 72 | } 73 | 74 | sendBitGoTx(); 75 | -------------------------------------------------------------------------------- /eth/examples/SKALE/listValidators.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0x840C8122433A5AA7ad60C1Bcdc36AB9DcCF761a5'; 14 | const ValidatorService = getContractsFactory('eth').getContract('SkaleValidatorService').instance(); 15 | ValidatorService.address = proxyAddress; 16 | 17 | /** 18 | * List all of the trusted validators that are registered within the SKALE Network. 19 | */ 20 | const { data, amount } = ValidatorService.methods().getTrustedValidators.call({}); 21 | const transaction = await bitGoWallet.send({ data, amount, address: ValidatorService.address, walletPassphrase }); 22 | console.dir(transaction); 23 | 24 | } 25 | 26 | sendBitGoTx(); 27 | -------------------------------------------------------------------------------- /eth/examples/SKALE/requestUndelegation.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | //parameter for the id of the undelegation request 14 | const idOfDelegation = 'ID of delegation to undelegate'; 15 | 16 | const proxyAddress = '0x06dD71dAb27C1A3e0B172d53735f00Bf1a66Eb79'; 17 | const DelegationController = getContractsFactory('eth').getContract('SkaleDelegationController').instance(); 18 | DelegationController.address = proxyAddress; 19 | 20 | /** 21 | * After the epoch starts all delegations that are accepted turns to DELEGATED state. 22 | * Token holders (delegators) can request undelegation once the delegation is in the DELEGATED state 23 | * But only their delegations will be “undelegated” once their delegation period is over. 24 | */ 25 | const { data, amount } = DelegationController.methods().requestUndelegation.call({ 26 | delegationId: idOfDelegation, 27 | }); 28 | const transaction = await bitGoWallet.send({ data, amount, address: DelegationController.address, walletPassphrase }); 29 | console.dir(transaction); 30 | 31 | } 32 | 33 | sendBitGoTx(); 34 | -------------------------------------------------------------------------------- /eth/examples/SKALE/requestUndelegationFromEscrow.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 14 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 15 | Allocator.address = proxyAddress; 16 | 17 | /** 18 | * Get the Escrow wallet address that is linked to the delegator's Bitgo wallet address 19 | */ 20 | let { data, amount } = Allocator.methods().getEscrowAddress.call({ 21 | beneficiary: bitGoWallet.getAddress(), 22 | }); 23 | const escrowAddress = await bitGoWallet.send({ data, amount, address: Allocator.address, walletPassphrase }); 24 | 25 | //Retrieve Escrow contract for delegator 26 | const Escrow = getContractsFactory('eth').getContract('SkaleEscrow').instance(); 27 | Escrow.address = escrowAddress; 28 | 29 | //parameter for the id of the undelegation request 30 | const idOfDelegation = 'ID of delegation to undelegate'; 31 | 32 | 33 | /** 34 | * Request to undelegate from the delegator's Escrow account. 35 | * 36 | * After the epoch starts all delegations that are accepted turns to DELEGATED state. 37 | * Token holders (delegators) can request undelegation once the delegation is in the DELEGATED state 38 | * But only their delegations will be “undelegated” once their delegation period is over. 39 | */ 40 | ({ data, amount } = Escrow.methods().requestUndelegation.call({ 41 | delegationId: idOfDelegation, 42 | })); 43 | const transaction = await bitGoWallet.send({ data, amount, address: Escrow.address, walletPassphrase }); 44 | console.dir(transaction); 45 | 46 | } 47 | 48 | sendBitGoTx(); 49 | -------------------------------------------------------------------------------- /eth/examples/SKALE/showLockedTokens.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const delegatorWalletAddress = 'delegator wallet address'; 14 | const proxyAddress = '0x1F2157Bf5C820f68826ef1DC71824816Ee795f41'; 15 | const TokenState = getContractsFactory('eth').getContract('SkaleTokenState').instance(); 16 | TokenState.address = proxyAddress; 17 | 18 | /** 19 | * List the amount of the tokens that are locked within the token holder (delegator) 20 | * wallet. 21 | */ 22 | const { data, amount } = TokenState.methods().getAndUpdateLockedAmount.call({ holder: delegatorWalletAddress }); 23 | const transaction = await bitGoWallet.send({ data, amount, address: TokenState.address, walletPassphrase }); 24 | console.dir(transaction); 25 | 26 | } 27 | 28 | sendBitGoTx(); 29 | -------------------------------------------------------------------------------- /eth/examples/SKALE/showLockedTokensForEscrow.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 14 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 15 | Allocator.address = proxyAddress; 16 | 17 | /** 18 | * Get the Escrow wallet address that is linked to the delegator's Bitgo wallet address 19 | */ 20 | let { data, amount } = Allocator.methods().getEscrowAddress.call({ 21 | beneficiary: bitGoWallet.getAddress(), 22 | }); 23 | const escrowAddress = await bitGoWallet.send({ data, amount, address: Allocator.address, walletPassphrase }); 24 | 25 | const tokenStateAddress = '0x1F2157Bf5C820f68826ef1DC71824816Ee795f41'; 26 | const TokenState = getContractsFactory('eth').getContract('SkaleTokenState').instance(); 27 | TokenState.address = tokenStateAddress; 28 | 29 | /** 30 | * List the amount of the tokens that are locked within the token holder's Escrow 31 | * contract. 32 | */ 33 | ({ data, amount } = TokenState.methods().getAndUpdateLockedAmount.call({ 34 | holder: escrowAddress, 35 | })); 36 | const transaction = await bitGoWallet.send({ data, amount, address: TokenState.address, walletPassphrase }); 37 | console.dir(transaction); 38 | 39 | } 40 | 41 | sendBitGoTx(); 42 | -------------------------------------------------------------------------------- /eth/examples/SKALE/withdrawBounty.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | //parameters needed for withdrawing bounties 14 | const idOfValidator = 'validator id'; 15 | const addressOfReceivingDelegator = 'token holder address'; 16 | 17 | const proxyAddress = '0x4eE5F270572285776814e32952446e9B7Ee15C86'; 18 | const Distributor = getContractsFactory('eth').getContract('SkaleDistributor').instance(); 19 | Distributor.address = proxyAddress; 20 | 21 | /** 22 | * Allows token holder (delegator) to withdraw bounty from a specific validator. 23 | * This needs to be called per validator in order to recieve all of the bounties. 24 | */ 25 | const { data, amount } = Distributor.methods().withdrawBounty.call({ 26 | validatorId: idOfValidator, 27 | address: addressOfReceivingDelegator, 28 | }); 29 | const transaction = await bitGoWallet.send({ data, amount, address: Distributor.address, walletPassphrase }); 30 | console.dir(transaction); 31 | 32 | } 33 | 34 | sendBitGoTx(); 35 | -------------------------------------------------------------------------------- /eth/examples/SKALE/withdrawBountyFromEscrow.ts: -------------------------------------------------------------------------------- 1 | import { BitGo } from 'bitgo'; 2 | import { getContractsFactory } from '../../../src/index'; 3 | 4 | 5 | async function sendBitGoTx(): Promise { 6 | 7 | const bitGo = new BitGo({ env: 'prod' }); 8 | const baseCoin = bitGo.coin('eth'); 9 | bitGo.authenticateWithAccessToken({ accessToken: 'access token' }); 10 | const bitGoWallet = await baseCoin.wallets().get({ id: 'wallet id' }); 11 | const walletPassphrase = 'password'; 12 | 13 | const proxyAddress = '0xB575c158399227b6ef4Dcfb05AA3bCa30E12a7ba'; 14 | const Allocator = getContractsFactory('eth').getContract('SkaleAllocator').instance(); 15 | Allocator.address = proxyAddress; 16 | 17 | /** 18 | * Get the Escrow wallet address that is linked to the delegator's Bitgo wallet address 19 | */ 20 | let { data, amount } = Allocator.methods().getEscrowAddress.call({ 21 | beneficiary: bitGoWallet.getAddress(), 22 | }); 23 | const escrowAddress = await bitGoWallet.send({ data, amount, address: Allocator.address, walletPassphrase }); 24 | 25 | //Retrieve Escrow contract for delegator 26 | const Escrow = getContractsFactory('eth').getContract('SkaleEscrow').instance(); 27 | Escrow.address = escrowAddress; 28 | 29 | //parameters needed for withdrawing bounties 30 | const idOfValidator = 'validator id'; 31 | 32 | /** 33 | * Withdraw bounty for delegator's Escrow account. 34 | * 35 | * Allows token holder (delegator) to withdraw bounty from a specific validator. 36 | * This needs to be called per validator in order to recieve all of the bounties. 37 | */ 38 | ({ data, amount } = Escrow.methods().withdrawBounty.call({ 39 | validatorId: idOfValidator, 40 | address: bitGoWallet.getAddress(), 41 | })); 42 | const transaction = await bitGoWallet.send({ data, amount, address: Escrow.address, walletPassphrase }); 43 | console.dir(transaction); 44 | 45 | } 46 | 47 | sendBitGoTx(); 48 | -------------------------------------------------------------------------------- /eth/examples/StandardERC20/approve.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'DAI'; 4 | const recipient = '0xadd62287c10d90f65fd3bf8bf94183df115c030a'; 5 | const tokenAmount = 1e18; // 1 DAI 6 | 7 | const daiContract = getContractsFactory('eth').getContract('StandardERC20').instance(tokenName); 8 | 9 | const { data, amount } = daiContract.methods().approve.call({ _spender: recipient, _value: tokenAmount.toString(10) }); 10 | 11 | console.log(`To approve ${tokenAmount} ${tokenName} to ${recipient}:\n`); 12 | console.log(`Data: ${data}`); 13 | console.log(`Amount: ${amount} ETH`); 14 | console.log(`To: ${daiContract.address}`); 15 | -------------------------------------------------------------------------------- /eth/examples/StandardERC20/transfer.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'DAI'; 4 | const recipient = '0xadd62287c10d90f65fd3bf8bf94183df115c030a'; 5 | const tokenAmount = 1e18; // 1 DAI 6 | 7 | const daiContract = getContractsFactory('eth').getContract('StandardERC20').instance(tokenName); 8 | 9 | const { data, amount } = daiContract.methods().transfer.call({ _to: recipient, _value: tokenAmount.toString(10) }); 10 | 11 | console.log(`To transfer ${tokenAmount} ${tokenName} to ${recipient}:\n`); 12 | console.log(`Data: ${data}`); 13 | console.log(`Amount: ${amount} ETH`); 14 | console.log(`To: ${daiContract.address}`); 15 | 16 | const decoder = getContractsFactory('eth').getDecoder(); 17 | 18 | const wbtcData = data.slice(2); 19 | const decoded = decoder.decode(Buffer.from(wbtcData, 'hex')); 20 | console.log(`\nTransfer decoded : \n`, decoded); 21 | -------------------------------------------------------------------------------- /eth/examples/Sushiswap/createLiquidityPool.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | async function sendBitGoTx() { 5 | const tokenA = 'DAI'; 6 | const tokenB = 'UNI'; 7 | const walletAddress = 'wallet addresses'; 8 | const amountADesired = 100e18; // amount of DAI desired 9 | const amountBDesired = 250e14; // amount of UNI desired 10 | const amountAMin = 995e17; //minimum amout of DAI 11 | const amountBMin = 254e14; // minimum amout of UNI 12 | const deadline = 'deadline'; 13 | 14 | const bitGo = new BitGo({ env: 'test', accessToken: 15 | 'accesstoken' }); 16 | const baseCoin = bitGo.coin('teth'); 17 | const bitGoWallet = await baseCoin 18 | .wallets() 19 | .get({ id: 'walletId' }); 20 | 21 | 22 | const liquidityPoolContract = getContractsFactory('eth') 23 | .getContract('SushiswapV2Router') 24 | .instance(); 25 | 26 | const tokenAContract = getContractsFactory('eth') 27 | .getContract('StandardERC20') 28 | .instance(tokenA); 29 | 30 | let { data, amount } = tokenAContract.methods().approve.call({ 31 | _spender: liquidityPoolContract.address, 32 | _value: amountADesired.toString(10), 33 | }); 34 | 35 | let transaction = await bitGoWallet.send({ 36 | data: data, amount: amount, address: tokenAContract.address, 37 | walletPassphrase: 'walletPassphrase', 38 | }); 39 | 40 | // we need to approve the amount of DAI for the liquidityPool contract to control 41 | console.log( 42 | `To approve ${amountADesired} ${tokenA} to DAI token contract, send:`, 43 | ); 44 | console.log(`Data: ${data}`); 45 | console.log(`Amount: ${amount}`); 46 | 47 | const tokenBContract = getContractsFactory('eth') 48 | .getContract('StandardERC20') 49 | .instance(tokenB); 50 | 51 | ({ data, amount } = tokenBContract.methods().approve.call({ 52 | _spender: liquidityPoolContract.address, 53 | _value: amountBDesired.toString(10), 54 | })); 55 | 56 | transaction = await bitGoWallet.send({ 57 | data: data, amount: amount, address: tokenBContract.address, 58 | walletPassphrase: 'walletPassphrase', 59 | }); 60 | 61 | //we need to approve the amount of UNI for the liquidityPool contract to control 62 | console.log( 63 | `To approve ${amountBDesired} ${tokenB} to UNI token contract, send:`, 64 | ); 65 | console.log(`Data: ${data}`); 66 | console.log(`Amount: ${amount}`); 67 | 68 | ({ data, amount } = liquidityPoolContract.methods().addLiquidity.call({ 69 | tokenA: tokenAContract.address, 70 | tokenB: tokenBContract.address, 71 | amountADesired: amountADesired.toString(10), 72 | amountBDesired: amountBDesired.toString(10), 73 | amountAMin: amountAMin.toString(10), 74 | amountBMin: amountBMin.toString(10), 75 | to: walletAddress, 76 | deadline: deadline, 77 | })); 78 | 79 | transaction = await bitGoWallet.send({ 80 | data: data, amount: amount, address: liquidityPoolContract.address, 81 | walletPassphrase: 'walletPassphrase', 82 | }); 83 | 84 | console.log(transaction); 85 | 86 | // Once the above txs are confirmed, we can create swap liquidity pool 87 | console.log(`To create liquidity pool with pair of ${tokenA} ${tokenB}, send: `); 88 | console.log(`${tokenA} amount: ${amountADesired} and ${tokenB} amount: ${amountBDesired} `); 89 | console.log(`to: ${liquidityPoolContract.address}`); 90 | } 91 | 92 | 93 | sendBitGoTx(); 94 | -------------------------------------------------------------------------------- /eth/examples/Sushiswap/kashiBorrow.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | import * as utils from '../utils'; 4 | import ethers from 'ethers'; 5 | import * as ethUtil from 'ethereumjs-util'; 6 | // Example to borrow DAI with WETH as Collateral in Kashi 7 | 8 | async function sendBitGoTx() { 9 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 10 | const baseCoin = bitGo.coin('teth'); 11 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 12 | /* 13 | * 24 ACTION_BENTO_SETAPPROVAL ParamNames user, _masterContract, approved, v, r, s. ABI encoding address, address, bool, uint8, bytes32, bytes32 14 | * for information in v, r, s visit https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md 15 | * example dataForAction24 ='0x 16 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab (wallet Address) 17 | * 0000000000000000000000002cba6ab6574646badc84f0544d05059e57a5dc42 (KashiPairMediumRiskV1 contract Address) 18 | * 0000000000000000000000000000000000000000000000000000000000000001 (approved) 19 | * 000000000000000000000000000000000000000000000000000000000000001c (v) 20 | * 45dcc6b8a59747de4424b7f11e5cfadd0399579d24ec91d433c8fda4d8b26246 (r) 21 | * 0d135ac427b217fe96dfbd86f97fe904f68dbb87538feec734f07af9ab9fd9c3' (s) 22 | * 5 ACTION_BORROW ParamNames amount, to. ABI encoding int256, address. 23 | * example dataForAction5 ='0x 24 | * 0000000000000000000000000000000000000000000000028c418afbbb5c0000 (amount) 25 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab' (to) 26 | * 20 ACTION_BENTO_DEPOSIT ParamNames token, to, amount, share. ABI encoding IERC20, address, int256, int256 27 | * example dataForAction20 ='0x 28 | * 0000000000000000000000000000000000000000000000000000000000000000 (IERC20) 29 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab (wallet Address) 30 | * 00000000000000000000000000000000000000000000000000470de4df820000 (amount) 31 | * 0000000000000000000000000000000000000000000000000000000000000000 (share) 32 | * 10 ACTION_ADD_COLLATERAL ParamNames share, to, skim. ABI encoding int256, address, bool 33 | * example dataForAction10 ='0x 34 | * fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe (share) 35 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab (wallet Address) 36 | * 0000000000000000000000000000000000000000000000000000000000000000 (skim) 37 | */ 38 | 39 | 40 | const sampleWalletAddress = '0x6c31cdbf161bad81f9eceb107d757cb85f2dbcab'; 41 | const masterContract = '0x2cba6ab6574646badc84f0544d05059e57a5dc42'; 42 | const approved = true; 43 | const nonce = 'nonce'; 44 | const kashiApprovalHash = utils.getKashiApprovalHash( 45 | sampleWalletAddress, 46 | masterContract, 47 | approved, 48 | nonce, 49 | ); 50 | 51 | const bentoBoxV1ContractAddress = 52 | '0xF5BCE5077908a1b7370B9ae04AdC565EBd643966'; 53 | const kashiBorrowContractAddress = 54 | '0x2cba6ab6574646badc84f0544d05059e57a5dc42'; 55 | const chainId = 1; 56 | const domainSeperatorHash = utils.getKashiDomainSeperatorHash( 57 | chainId, 58 | bentoBoxV1ContractAddress, 59 | ); 60 | const digest = utils.getMasterContractApprovalHash( 61 | domainSeperatorHash, 62 | kashiApprovalHash, 63 | ); 64 | 65 | const privateKeyHex = 'privateKeyHex'; 66 | const privkey = Buffer.from(privateKeyHex.replace(/^0x/i, ''), 'hex'); 67 | const signature = ethUtil.ecsign(digest, privkey); 68 | 69 | let dataForAction24 = utils.stripHexPrefix( 70 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 71 | ); 72 | dataForAction24 += utils.stripHexPrefix( 73 | ethers.utils.hexZeroPad(kashiBorrowContractAddress, 32), 74 | ); 75 | dataForAction24 += utils.stripHexPrefix(ethers.utils.hexZeroPad('0x1', 32)); 76 | dataForAction24 += utils.stripHexPrefix( 77 | ethers.utils.hexZeroPad(ethers.utils.hexlify(signature.v), 32), 78 | ); 79 | dataForAction24 += utils.stripHexPrefix( 80 | ethers.utils.hexZeroPad(signature.r.toString('hex'), 32), 81 | ); 82 | dataForAction24 += utils.stripHexPrefix( 83 | ethers.utils.hexZeroPad(signature.s.toString('hex'), 32), 84 | ); 85 | 86 | const amountToBorrow = 50e18; 87 | let dataForAction5 = utils.stripHexPrefix( 88 | ethers.utils.hexZeroPad( 89 | ethUtil.addHexPrefix(amountToBorrow.toString(16)), 90 | 32, 91 | ), 92 | ); 93 | dataForAction5 += utils.stripHexPrefix( 94 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 95 | ); 96 | 97 | const amountToDeposit = 1e18; 98 | let dataForAction20 = utils.stripHexPrefix(ethers.utils.hexZeroPad('0x', 32)); 99 | dataForAction20 += utils.stripHexPrefix( 100 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 101 | ); 102 | dataForAction20 += utils.stripHexPrefix( 103 | ethers.utils.hexZeroPad( 104 | ethUtil.addHexPrefix(amountToDeposit.toString(16)), 105 | 32, 106 | ), 107 | ); 108 | const share = 0; 109 | dataForAction20 += utils.stripHexPrefix( 110 | ethers.utils.hexZeroPad(ethUtil.addHexPrefix(share.toString(16)), 32), 111 | ); 112 | 113 | let dataForAction10 = utils.stripHexPrefix( 114 | ethers.utils.hexZeroPad( 115 | ethUtil.addHexPrefix(utils.MAX_VALUE_SHARE.toString(16)), 116 | 32, 117 | ), 118 | ); 119 | dataForAction10 += utils.stripHexPrefix( 120 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 121 | ); 122 | const skim = 0; 123 | dataForAction10 += utils.stripHexPrefix( 124 | ethers.utils.hexZeroPad(skim.toString(16), 32), 125 | ); 126 | 127 | const actions = ['24', '5', '20', '10']; 128 | const values = ['0', '0', amountToDeposit, '0']; 129 | const datas = [ 130 | ethUtil.addHexPrefix(dataForAction24), 131 | ethUtil.addHexPrefix(dataForAction5), 132 | ethUtil.addHexPrefix(dataForAction20), 133 | ethUtil.addHexPrefix(dataForAction10), 134 | ]; 135 | const borrowContract = getContractsFactory('eth') 136 | .getContract('KashiPairMediumRiskV1') 137 | .instance(); 138 | 139 | const { data, amount } = borrowContract.methods().cook.call({ 140 | actions, 141 | values, 142 | datas, 143 | }); 144 | 145 | const transaction = await bitGoWallet.send({ 146 | data: data, 147 | amount: amount, 148 | address: borrowContract.address, 149 | walletPassphrase: 'walletPassphrase', 150 | }); 151 | 152 | console.log(transaction); 153 | } 154 | 155 | sendBitGoTx(); 156 | -------------------------------------------------------------------------------- /eth/examples/Sushiswap/kashiLend.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | import * as utils from '../utils'; 4 | import ethers from 'ethers'; 5 | import * as ethUtil from 'ethereumjs-util'; 6 | // Example to lend USDT in Kashi 7 | 8 | async function sendBitGoTx() { 9 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 10 | const baseCoin = bitGo.coin('teth'); 11 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 12 | 13 | /* 14 | * 24 ACTION_BENTO_SETAPPROVAL ParamNames user, _masterContract, approved, v, r, s. ABI encoding address, address, bool, uint8, bytes32, bytes32 15 | * for information in v, r, s visit https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md 16 | * userAddress= walletAddress 17 | * _masterContract=KashiPairMediumRiskV1 contract Address 18 | * example dataForAction24 ='0x 19 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab (wallet Address) 20 | * 0000000000000000000000002cba6ab6574646badc84f0544d05059e57a5dc42 (KashiPairMediumRiskV1 contract Address) 21 | * 0000000000000000000000000000000000000000000000000000000000000001 (approved) 22 | * 000000000000000000000000000000000000000000000000000000000000001c (v) 23 | * 45dcc6b8a59747de4424b7f11e5cfadd0399579d24ec91d433c8fda4d8b26246 (r) 24 | * 0d135ac427b217fe96dfbd86f97fe904f68dbb87538feec734f07af9ab9fd9c3' (s) 25 | * 26 | * 20 ACTION_BENTO_DEPOSIT ParamNames token, to, amount, share. ABI encoding IERC20, address, int256, int256 27 | * example dataForAction20='0x 28 | * 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7 (USDT contract Address) 29 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab (wallet Address) 30 | * 00000000000000000000000000000000000000000000000000000000017b31ee (amount) 31 | * 0000000000000000000000000000000000000000000000000000000000000000' (share) 32 | * 1 ACTION_ADD_ASSET ParamNames share, to, skim. ABI encoding int256, address, bool 33 | * example dataForAction1='0x 34 | * fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe (share) 35 | * 0000000000000000000000006c31cdbf161bad81f9eceb107d757cb85f2dbcab (wallet Address) 36 | * 0000000000000000000000000000000000000000000000000000000000000000' (skim) 37 | */ 38 | const actions = ['24', '20', '1']; 39 | const values = ['0', '0', '0']; 40 | const sampleWalletAddress = '0x6c31cdbf161bad81f9eceb107d757cb85f2dbcab'; 41 | const masterContract = '0x2cba6ab6574646badc84f0544d05059e57a5dc42'; 42 | const approved = true; 43 | const nonce = 'nonce'; 44 | const kashiApprovalHash = utils.getKashiApprovalHash( 45 | sampleWalletAddress, 46 | masterContract, 47 | approved, 48 | nonce, 49 | ); 50 | 51 | const bentoBoxV1ContractAddress = 52 | '0xF5BCE5077908a1b7370B9ae04AdC565EBd643966'; 53 | const kashiBorrowContractAddress = 54 | '0x2cba6ab6574646badc84f0544d05059e57a5dc42'; 55 | const chainId = 1; 56 | const domainSeperatorHash = utils.getKashiDomainSeperatorHash( 57 | chainId, 58 | bentoBoxV1ContractAddress, 59 | ); 60 | const digest = utils.getMasterContractApprovalHash( 61 | domainSeperatorHash, 62 | kashiApprovalHash, 63 | ); 64 | 65 | const privateKeyHex = 'privateKeyHex'; 66 | const privkey = Buffer.from(privateKeyHex.replace(/^0x/i, ''), 'hex'); 67 | const signature = ethUtil.ecsign(digest, privkey); 68 | 69 | let dataForAction24 = utils.stripHexPrefix( 70 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 71 | ); 72 | dataForAction24 += utils.stripHexPrefix( 73 | ethers.utils.hexZeroPad(kashiBorrowContractAddress, 32), 74 | ); 75 | dataForAction24 += utils.stripHexPrefix(ethers.utils.hexZeroPad('0x1', 32)); 76 | dataForAction24 += utils.stripHexPrefix( 77 | ethers.utils.hexZeroPad(ethers.utils.hexlify(signature.v), 32), 78 | ); 79 | dataForAction24 += utils.stripHexPrefix( 80 | ethers.utils.hexZeroPad(signature.r.toString('hex'), 32), 81 | ); 82 | dataForAction24 += utils.stripHexPrefix( 83 | ethers.utils.hexZeroPad(signature.s.toString('hex'), 32), 84 | ); 85 | 86 | const amountToDeposit = 1e18; 87 | let dataForAction20 = utils.stripHexPrefix(ethers.utils.hexZeroPad('0x', 32)); 88 | dataForAction20 += utils.stripHexPrefix( 89 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 90 | ); 91 | dataForAction20 += utils.stripHexPrefix( 92 | ethers.utils.hexZeroPad( 93 | ethUtil.addHexPrefix(amountToDeposit.toString(16)), 94 | 32, 95 | ), 96 | ); 97 | const share = 0; 98 | dataForAction20 += utils.stripHexPrefix( 99 | ethers.utils.hexZeroPad(ethUtil.addHexPrefix(share.toString(16)), 32), 100 | ); 101 | 102 | let dataForAction1 = utils.stripHexPrefix( 103 | ethers.utils.hexZeroPad( 104 | ethUtil.addHexPrefix(utils.MAX_VALUE_SHARE.toString(16)), 105 | 32, 106 | ), 107 | ); 108 | dataForAction1 += utils.stripHexPrefix( 109 | ethers.utils.hexZeroPad(sampleWalletAddress, 32), 110 | ); 111 | const skim = 0; 112 | dataForAction1 += utils.stripHexPrefix( 113 | ethers.utils.hexZeroPad(skim.toString(16), 32), 114 | ); 115 | 116 | const datas = [ethUtil.addHexPrefix(dataForAction24), ethUtil.addHexPrefix(dataForAction20), ethUtil.addHexPrefix(dataForAction1)]; 117 | const lendContract = getContractsFactory('eth') 118 | .getContract('KashiPairMediumRiskV1') 119 | .instance(); 120 | 121 | 122 | const { data, amount } = lendContract.methods().cook.call({ 123 | actions, 124 | values, 125 | datas, 126 | }); 127 | 128 | const transaction = await bitGoWallet.send({ 129 | data: data, 130 | amount: amount, 131 | address: lendContract.address, 132 | walletPassphrase: 'walletPassphrase', 133 | }); 134 | 135 | console.log(transaction); 136 | 137 | 138 | } 139 | 140 | sendBitGoTx(); 141 | -------------------------------------------------------------------------------- /eth/examples/Sushiswap/removeLiquidityPool.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | import * as utils from '../utils'; 4 | import * as ethUtil from 'ethereumjs-util'; 5 | async function sendBitGoTx() { 6 | const tokenAContractAddress = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984'; //UNI 7 | const tokenBContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; //DAI 8 | 9 | const walletAddress = '0x61E64B5224f88944222c4Aa7CCE1809c17106De5'; 10 | const liquidity = 220e9; 11 | const amountAMin = 20e15; 12 | const amountBMin = 99e18; 13 | const deadline = 'deadline'; 14 | 15 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 16 | const baseCoin = bitGo.coin('teth'); 17 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 18 | const liquidityPoolContract = getContractsFactory('eth') 19 | .getContract('SushiswapV2Router') 20 | .instance(); 21 | 22 | const chainId = 1; 23 | const sushiSwapV2FactoryContractAddress = '0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac'; 24 | const sampleWalletAddress = '0x6c31cdbf161bad81f9eceb107d757cb85f2dbcab'; 25 | const spender = liquidityPoolContract.address; 26 | const value = liquidity.toString(10); 27 | const nonce = 'nonce'; 28 | const name = 'SushiSwap LP Token'; 29 | const permitApprovalHash = utils.getUniSushiSwapV2ApprovalHash(sampleWalletAddress, spender, value, nonce, deadline); 30 | const domainSeperatorHash = utils.getUniSushiSwapV2PairDomainSeperatorHash(name, chainId, sushiSwapV2FactoryContractAddress); 31 | const digest = utils.getMasterContractApprovalHash(domainSeperatorHash, permitApprovalHash); 32 | const privateKeyHex = 'privateKeyHex'; 33 | const privkey = Buffer.from(privateKeyHex.replace(/^0x/i, ''), 'hex'); 34 | const signature = ethUtil.ecsign(digest, privkey); 35 | 36 | const v = signature.v; 37 | const r = ethUtil.addHexPrefix(signature.r.toString('hex')); 38 | const s = ethUtil.addHexPrefix(signature.s.toString('hex')); 39 | 40 | 41 | const { data, amount } = liquidityPoolContract 42 | .methods() 43 | .removeLiquidityWithPermit.call({ 44 | tokenA: tokenAContractAddress, 45 | tokenB: tokenBContractAddress, 46 | liquidity: liquidity.toString(10), 47 | amountAMin: amountAMin.toString(10), 48 | amountBMin: amountBMin.toString(10), 49 | to: walletAddress, 50 | deadline: deadline, 51 | v: v, 52 | r: r, 53 | s: s, 54 | }); 55 | 56 | const transaction = await bitGoWallet.send({ 57 | data: data, 58 | amount: amount, 59 | address: liquidityPoolContract.address, 60 | walletPassphrase: 'walletPassphrase', 61 | }); 62 | 63 | console.log(transaction); 64 | } 65 | 66 | sendBitGoTx(); 67 | -------------------------------------------------------------------------------- /eth/examples/Sushiswap/swap.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | 5 | // Example to swap from 0.01 ETH to DAI 6 | 7 | async function sendBitGoTx() { 8 | const DAIContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; 9 | const wrappedEtherContractAddress = '0xd0A1E359811322d97991E03f863a0C30C2cF029C'; 10 | const toAddress = 'wallet address'; 11 | const amountOutMin = 50e17; 12 | const deadline = 'deadline'; 13 | const swapRouter = getContractsFactory('eth').getContract('SushiswapV2Router').instance(); 14 | const path = [wrappedEtherContractAddress, DAIContractAddress]; 15 | 16 | const txInput = swapRouter.methods().swapExactETHForTokens. 17 | call({ amountOutMin: amountOutMin.toString(10), path: path, to: toAddress, deadline: deadline }); 18 | 19 | txInput.amount = 1e16; 20 | console.log(`To swap ETH to DAI with SushiswapV2Router contract, send:`); 21 | console.log(`Data: ${txInput.data}`); 22 | console.log(`Amount: ${txInput.amount}`); 23 | console.log(`To: ${swapRouter.address}`); 24 | 25 | 26 | const bitGo = new BitGo({ env: 'test', accessToken: 27 | 'accesstoken' }); 28 | const baseCoin = bitGo.coin('teth'); 29 | const bitGoWallet = await baseCoin 30 | .wallets() 31 | .get({ id: 'walletId' }); 32 | 33 | 34 | const transaction = await bitGoWallet.send({ 35 | data: txInput.data, amount: txInput.amount, address: swapRouter.address, 36 | walletPassphrase: 'walletPassphrase', 37 | }); 38 | 39 | console.log(transaction); 40 | } 41 | 42 | sendBitGoTx(); 43 | -------------------------------------------------------------------------------- /eth/examples/Uniswap/createLiquidityPoolV2.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | //create DAI/ETH Liquidity Pool 5 | async function sendBitGoTx() { 6 | const token = 'DAI'; 7 | const walletAddress = 'wallet address'; 8 | const amountTokenDesired = 54e18; 9 | const amountTokenMin = 53e18; 10 | const amountETHMin = 995e13; 11 | const deadline = 'deadline'; 12 | 13 | const bitGo = new BitGo({ env: 'test', accessToken: 14 | 'accesstoken' }); 15 | const baseCoin = bitGo.coin('teth'); 16 | const bitGoWallet = await baseCoin 17 | .wallets() 18 | .get({ id: 'walletId' }); 19 | 20 | 21 | const liquidityPoolContract = getContractsFactory('eth') 22 | .getContract('UniswapV2SwapRouter') 23 | .instance(); 24 | 25 | // we need to approve the amount of DAI for the liquidityPool contract to control 26 | const tokenContract = getContractsFactory('eth') 27 | .getContract('StandardERC20') 28 | .instance(token); 29 | 30 | let { data, amount } = tokenContract.methods().approve.call({ 31 | _spender: liquidityPoolContract.address, 32 | _value: amountTokenDesired.toString(10), 33 | }); 34 | 35 | let transaction = await bitGoWallet.send({ 36 | data: data, amount: amount, address: tokenContract.address, 37 | walletPassphrase: 'walletPassphrase', 38 | }); 39 | 40 | console.log( 41 | `To approve ${amountTokenDesired} ${token} to DAI token contract, send:`, 42 | ); 43 | console.log(`Data: ${data}`); 44 | console.log(`Amount: ${amount}`); 45 | 46 | 47 | ({ data, amount } = liquidityPoolContract.methods().addLiquidityETH.call({ 48 | token: tokenContract.address, 49 | amountTokenDesired: amountTokenDesired.toString(10), 50 | amountTokenMin: amountTokenMin.toString(10), 51 | amountETHMin: amountETHMin.toString(10), 52 | to: walletAddress, 53 | deadline, 54 | })); 55 | 56 | transaction = await bitGoWallet.send({ 57 | data: data, amount: amount, address: liquidityPoolContract.address, 58 | walletPassphrase: 'walletPassphrase', 59 | }); 60 | 61 | console.log(transaction); 62 | 63 | } 64 | 65 | 66 | sendBitGoTx(); 67 | -------------------------------------------------------------------------------- /eth/examples/Uniswap/createLiquidityPoolV3.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | async function sendBitGoTx() { 5 | const token0 = 'UNI'; 6 | const token1 = 'DAI'; 7 | const token0ContractAddress = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984'; 8 | const token1ContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; 9 | const walletAddress = '0x6f32a7e465d50f61df96dfffc5bfb6d4059c7cd6'; 10 | const fee = '3000'; 11 | const tickLower = '-887220'; 12 | const tickUpper = '887220'; 13 | const amount0Desired = 148e14; 14 | const amount1Desired = 499e17; 15 | const amount0Min = 147e14; 16 | const amount1Min = 498e17; 17 | const deadline = 'deadline'; 18 | 19 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 20 | const baseCoin = bitGo.coin('teth'); 21 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 22 | 23 | const liquidityPoolContract = getContractsFactory('eth') 24 | .getContract('UniswapV3NonfungiblePositionManager') 25 | .instance(); 26 | 27 | const token0Contract = getContractsFactory('eth') 28 | .getContract('StandardERC20') 29 | .instance(token0); 30 | 31 | let { data, amount } = token0Contract.methods().approve.call({ 32 | _spender: liquidityPoolContract.address, 33 | _value: amount0Desired.toString(10), 34 | }); 35 | 36 | // we need to approve the amount of UNI for the liquidityPool contract to control 37 | console.log( 38 | `To approve ${amount0Desired} ${token0} to UNI token contract, send:`, 39 | ); 40 | console.log(`Data: ${data}`); 41 | console.log(`Amount: ${amount}`); 42 | 43 | let transaction = await bitGoWallet.send({ 44 | data: data, 45 | amount: amount, 46 | address: token0Contract.address, 47 | walletPassphrase: 'walletPassphrase', 48 | }); 49 | 50 | const token1Contract = getContractsFactory('eth') 51 | .getContract('StandardERC20') 52 | .instance(token1); 53 | 54 | ({ data, amount } = token1Contract.methods().approve.call({ 55 | _spender: liquidityPoolContract.address, 56 | _value: amount1Desired.toString(10), 57 | })); 58 | 59 | //we need to approve the amount of DAI for the liquidityPool contract to control 60 | console.log( 61 | `To approve ${amount1Desired} ${token1} to DAI token contract, send:`, 62 | ); 63 | console.log(`Data: ${data}`); 64 | console.log(`Amount: ${amount}`); 65 | 66 | transaction = await bitGoWallet.send({ 67 | data: data, 68 | amount: amount, 69 | address: token1Contract.address, 70 | walletPassphrase: 'walletPassphrase', 71 | }); 72 | 73 | ({ data, amount } = liquidityPoolContract.methods().mint.call({ 74 | token0: token0ContractAddress, 75 | token1: token1ContractAddress, 76 | fee: fee, 77 | tickLower: tickLower, 78 | tickUpper: tickUpper, 79 | amount0Desired: amount0Desired.toString(10), 80 | amount1Desired: amount1Desired.toString(10), 81 | amount0Min: amount0Min.toString(10), 82 | amount1Min: amount1Min.toString(10), 83 | recipient: walletAddress, 84 | deadline: deadline, 85 | })); 86 | 87 | // Once the above txs are confirmed, we can create swap liquidity pool 88 | console.log( 89 | `To create liquidity pool with pair of ${token0} ${token1}, send: `, 90 | ); 91 | console.log( 92 | `${token0} amount: ${amount0Desired} and ${token1} amount: ${amount1Desired} `, 93 | ); 94 | console.log(`to: ${liquidityPoolContract.address}`); 95 | 96 | transaction = await bitGoWallet.send({ 97 | data: data, 98 | amount: amount, 99 | address: liquidityPoolContract.address, 100 | walletPassphrase: 'walletPassphrase', 101 | }); 102 | 103 | console.log(transaction); 104 | } 105 | 106 | sendBitGoTx(); 107 | -------------------------------------------------------------------------------- /eth/examples/Uniswap/removeLiquidityPoolV2.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | import * as utils from '../utils'; 4 | import * as ethUtil from 'ethereumjs-util'; 5 | //remove DAI/ETH Liquidity Pool 6 | async function sendBitGoTx() { 7 | const liquidity = 10e18; 8 | const tokenContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; //DAI 9 | const walletAddress = '0x61E64B5224f88944222c4Aa7CCE1809c17106De5'; 10 | const amountTokenMin = 99e18; 11 | const amountETHMin = 9e15; 12 | const deadline = 'deadline'; 13 | 14 | 15 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 16 | const baseCoin = bitGo.coin('teth'); 17 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 18 | 19 | const liquidityPoolContract = getContractsFactory('eth') 20 | .getContract('UniswapV2SwapRouter') 21 | .instance(); 22 | const chainId = 1; 23 | const uniSwapV2FactoryContractAddress = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f'; 24 | const sampleWalletAddress = '0x6c31cdbf161bad81f9eceb107d757cb85f2dbcab'; 25 | const spender = liquidityPoolContract.address; 26 | const value = liquidity.toString(10); 27 | const nonce = 'nonce'; 28 | const name = 'Uniswap V2'; 29 | const permitApprovalHash = utils.getUniSushiSwapV2ApprovalHash(sampleWalletAddress, spender, value, nonce, deadline); 30 | const domainSeperatorHash = utils.getUniSushiSwapV2PairDomainSeperatorHash(name, chainId, uniSwapV2FactoryContractAddress); 31 | const digest = utils.getMasterContractApprovalHash(domainSeperatorHash, permitApprovalHash); 32 | const privateKeyHex = 'privateKeyHex'; 33 | const privkey = Buffer.from(privateKeyHex.replace(/^0x/i, ''), 'hex'); 34 | const signature = ethUtil.ecsign(digest, privkey); 35 | 36 | const v = signature.v; 37 | const r = ethUtil.addHexPrefix(signature.r.toString('hex')); 38 | const s = ethUtil.addHexPrefix(signature.s.toString('hex')); 39 | 40 | const { data, amount } = liquidityPoolContract 41 | .methods() 42 | .addLiquidityETH.call({ 43 | token: tokenContractAddress, 44 | liquidity: liquidity.toString(10), 45 | amountTokenMin: amountTokenMin.toString(10), 46 | amountETHMin: amountETHMin.toString(10), 47 | to: walletAddress, 48 | deadline, 49 | v: v, 50 | r: r, 51 | s: s, 52 | }); 53 | 54 | const transaction = await bitGoWallet.send({ 55 | data: data, 56 | amount: amount, 57 | address: liquidityPoolContract.address, 58 | walletPassphrase: 'walletPassphrase', 59 | }); 60 | 61 | console.log(transaction); 62 | } 63 | 64 | sendBitGoTx(); 65 | -------------------------------------------------------------------------------- /eth/examples/Uniswap/removeLiquidityPoolV3.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | //remove DAI/ETH Liquidity Pool 5 | async function sendBitGoTx() { 6 | 7 | const DAIContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; 8 | const tokenId = 'tokenId'; // you can get the id calling balanceOf and tokenOfOwnerByIndex 9 | const liquidity = 18e17; 10 | const amount0Min = 80e15; //eth 11 | const amount1Min = 40e18; //dai 12 | const deadline = 'deadline'; 13 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 14 | const baseCoin = bitGo.coin('teth'); 15 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 16 | 17 | const liquidityPoolContract = getContractsFactory('eth') 18 | .getContract('UniswapV3NonfungiblePositionManager') 19 | .instance(); 20 | 21 | const data1 = liquidityPoolContract 22 | .methods() 23 | .decreaseLiquidity.call({ 24 | tokenId, 25 | liquidity: liquidity.toString(10), 26 | amount0Min: amount0Min.toString(10), 27 | amount1Min: amount1Min.toString(10), 28 | deadline, 29 | }); 30 | 31 | const recipient = 'walletAddress'; 32 | const amountMax = '340282366920938463463374607431768211455'; 33 | 34 | const data2 = liquidityPoolContract 35 | .methods() 36 | .collect.call({ 37 | tokenId, 38 | recipient, 39 | amount0Max: amountMax, 40 | amount1Max: amountMax, 41 | }); 42 | 43 | const data3 = liquidityPoolContract 44 | .methods() 45 | .unwrapWETH9.call({ 46 | amountMinimum: amount1Min.toString(10), 47 | recipient, 48 | }); 49 | 50 | const data4 = liquidityPoolContract 51 | .methods() 52 | .sweepToken.call({ 53 | token: DAIContractAddress, 54 | amountMinimum: amount0Min.toString(10), 55 | recipient, 56 | }); 57 | const dataBytes = [data1.data, data2.data, data3.data, data4.data]; 58 | 59 | const { data, amount } = liquidityPoolContract 60 | .methods() 61 | .multicall.call({ data: dataBytes }); 62 | 63 | 64 | const transaction = await bitGoWallet.send({ 65 | data: data, 66 | amount: amount, 67 | address: liquidityPoolContract.address, 68 | walletPassphrase: 'walletPassphrase', 69 | }); 70 | 71 | console.log(transaction); 72 | } 73 | 74 | sendBitGoTx(); 75 | -------------------------------------------------------------------------------- /eth/examples/Uniswap/swapV2.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | 5 | // Example to swap from 0.01 ETH to DAI 6 | 7 | async function sendBitGoTx() { 8 | const DAIContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; 9 | const amountOutMin = 50e17; 10 | const wrappedEtherContractAddress = '0xd0A1E359811322d97991E03f863a0C30C2cF029C'; 11 | const toAddress = 'walletAddress'; 12 | const swapRouter = getContractsFactory('eth').getContract('UniswapV2SwapRouter').instance(); 13 | const path = [wrappedEtherContractAddress, DAIContractAddress]; 14 | const deadline = 'deadline'; 15 | const ethAmount = 1e16; 16 | 17 | const txInput = swapRouter.methods().swapExactETHForTokens. 18 | call({ amountOutMin: amountOutMin.toString(10), path: path, to: toAddress, deadline: deadline }); 19 | txInput.amount = ethAmount.toString(10); 20 | console.log(`To swap ETH to DAI with UniwapV2Router contract, send:`); 21 | console.log(`Data: ${txInput.data}`); 22 | console.log(`Amount: ${txInput.amount}`); 23 | console.log(`To: ${swapRouter.address}`); 24 | 25 | 26 | const bitGo = new BitGo({ env: 'test', accessToken: 27 | 'accesstoken' }); 28 | const baseCoin = bitGo.coin('teth'); 29 | const bitGoWallet = await baseCoin 30 | .wallets() 31 | .get({ id: 'walletId' }); 32 | 33 | 34 | const transaction = await bitGoWallet.send({ 35 | data: txInput.data, amount: txInput.amount, address: swapRouter.address, 36 | walletPassphrase: 'walletPassphrase', 37 | }); 38 | 39 | console.log(transaction); 40 | } 41 | 42 | sendBitGoTx(); 43 | -------------------------------------------------------------------------------- /eth/examples/Uniswap/swapV3.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | import { BitGo } from 'bitgo'; 3 | 4 | // Example to swap from 0.01 ETH to DAI 5 | 6 | async function sendBitGoTx() { 7 | const bitGo = new BitGo({ env: 'test', accessToken: 'accesstoken' }); 8 | const baseCoin = bitGo.coin('teth'); 9 | const bitGoWallet = await baseCoin.wallets().get({ id: 'walletId' }); 10 | 11 | const DAIContractAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; 12 | const amountOutMinimum = 50e17; 13 | const amountIn = 1e16; 14 | const wrappedEtherContractAddress = '0xd0A1E359811322d97991E03f863a0C30C2cF029C'; 15 | const walletAddress = '0x6f32a7e465d50f61df96dfffc5bfb6d4059c7cd6'; 16 | const fee = '3000'; 17 | const sqrtPriceLimitX96 = '0'; 18 | const deadline = 'deadline'; 19 | 20 | const swapRouter = getContractsFactory('eth') 21 | .getContract('UniswapV3SwapRouter') 22 | .instance(); 23 | const txInput = swapRouter.methods().exactInputSingle.call({ 24 | tokenIn: wrappedEtherContractAddress, 25 | tokenOut: DAIContractAddress, 26 | fee: fee, 27 | recipient: walletAddress, 28 | deadline: deadline, 29 | amountIn: amountIn.toString(10), 30 | amountOutMinimum: amountOutMinimum, 31 | sqrtPriceLimitX96: sqrtPriceLimitX96, 32 | }); 33 | 34 | txInput.amount = amountIn.toString(10); 35 | const transaction = await bitGoWallet.send({ 36 | data: txInput.data, 37 | amount: txInput.amount, 38 | address: swapRouter.address, 39 | walletPassphrase: 'walletPassphrase', 40 | }); 41 | 42 | console.log(transaction); 43 | } 44 | 45 | sendBitGoTx(); 46 | -------------------------------------------------------------------------------- /eth/examples/WrappedToken/balanceOf.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedToken').instance(tokenName); 6 | 7 | const result = contract.methods().balanceOf.call({_owner: '0xd5ADdE17feD8baed3F32b84AF05B8F2816f7b560'}) 8 | console.log(result) 9 | 10 | const decoder = getContractsFactory('eth').getDecoder(); 11 | 12 | const wdogeData = result.data.slice(2); 13 | const decoded = decoder.decode(Buffer.from(wdogeData, 'hex')); 14 | console.log(decoded) 15 | 16 | -------------------------------------------------------------------------------- /eth/examples/WrappedToken/burn.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedToken').instance(tokenName); 6 | 7 | const result = contract.methods().burn.call({ value: '10' }); 8 | console.log(result) 9 | 10 | const decoder = getContractsFactory('eth').getDecoder(); 11 | 12 | const wdogeData = result.data.slice(2); 13 | const decoded = decoder.decode(Buffer.from(wdogeData, 'hex')); 14 | console.log(decoded) 15 | -------------------------------------------------------------------------------- /eth/examples/WrappedToken/mint.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedToken').instance(tokenName); 6 | 7 | const result = contract.methods().mint.call({ _to: '0xD037CA7A2B62c66B0F01CB2C93B978493dcD06d6', _amount: '100' }); 8 | console.log(result) 9 | 10 | const decoder = getContractsFactory('eth').getDecoder(); 11 | 12 | const wdogeData = result.data.slice(2); 13 | const decoded = decoder.decode(Buffer.from(wdogeData, 'hex')); 14 | console.log(decoded) 15 | 16 | -------------------------------------------------------------------------------- /eth/examples/WrappedToken/transfer.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedToken').instance(tokenName); 6 | 7 | const result = contract.methods().transfer.call({_to: '0xd5ADdE17feD8baed3F32b84AF05B8F2816f7b560', _value: 12}) 8 | console.log(result) 9 | 10 | const decoder = getContractsFactory('eth').getDecoder(); 11 | 12 | const wdogeData = result.data.slice(2); 13 | const decoded = decoder.decode(Buffer.from(wdogeData, 'hex')); 14 | console.log(decoded) 15 | 16 | -------------------------------------------------------------------------------- /eth/examples/WrappedTokenControllerV1/transferOwnership.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedTokenControllerV1').instance(tokenName); 6 | 7 | const result = contract.methods().transferOwnership.call({ newOwner: '0xD037CA7A2B62c66B0F01CB2C93B978493dcD06d6' }); 8 | console.log(result) 9 | 10 | const decoder = getContractsFactory('eth').getDecoder(); 11 | 12 | const wdogeData = result.data.slice(2); 13 | const decoded = decoder.decode(Buffer.from(wdogeData, 'hex')); 14 | console.log(decoded) 15 | 16 | -------------------------------------------------------------------------------- /eth/examples/WrappedTokenFactoryV1/addMintRequest.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedTokenFactoryV1').instance(tokenName); 6 | 7 | const custodianDepositAddress = '0xd5ADdE17feD8baed3F32b84AF05B8F2816f7b560'; 8 | const txId = 'f3b566050a4b57ca2acd1acdf9221a911d3740d9e7f9e0f3ddb468988f454ea1'; 9 | const amount = '10'; 10 | 11 | const result = contract.methods().addMintRequest.call({ amount: amount, txid: txId, depositAddress: custodianDepositAddress }); 12 | console.log('encoded', result); 13 | 14 | const decoder = getContractsFactory('eth').getDecoder(); 15 | 16 | const data = result.data; 17 | console.log(data); 18 | 19 | /** Decode with string data */ 20 | const decodedFromString = decoder.decode(data); 21 | console.log(`\n AddMintRequest decoded from string: \n`, decodedFromString); 22 | 23 | /** Decode with Buffer data*/ 24 | const decodedFromBuffer = decoder.decode(Buffer.from(data.slice(2), 'hex')); 25 | console.log(`\n AddMintRequest decoded from Buffer: \n`, decodedFromBuffer); 26 | -------------------------------------------------------------------------------- /eth/examples/WrappedTokenMembers/setCustodian.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WDOGE'; 4 | 5 | const contract = getContractsFactory('eth').getContract('WrappedTokenMembers').instance(tokenName); 6 | 7 | const result = contract.methods().setCustodian.call({ _custodian: '0xD037CA7A2B62c66B0F01CB2C93B978493dcD06d6' }); 8 | 9 | console.log(result) 10 | 11 | const decoder = getContractsFactory('eth').getDecoder(); 12 | 13 | const wdogeData = result.data.slice(2); 14 | const decoded = decoder.decode(Buffer.from(wdogeData, 'hex')); 15 | console.log(decoded) 16 | 17 | -------------------------------------------------------------------------------- /eth/examples/utils.ts: -------------------------------------------------------------------------------- 1 | import * as abi from 'ethereumjs-abi'; 2 | import ethers from 'ethers'; 3 | 4 | 5 | const APPROVAL_SIGNATURE_HASH = 6 | ethers.utils.keccak256(ethers.utils.toUtf8Bytes('SetMasterContractApproval(string warning,address user,address masterContract,bool approved,uint256 nonce)')); 7 | const WARNING_MESSAGE_HASH = 8 | ethers.utils.keccak256(ethers.utils.toUtf8Bytes('Give FULL access to funds in (and approved to) BentoBox?')); 9 | const EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = '\x19\x01'; 10 | const DOMAIN_SEPARATOR_SIGNATURE_HASH = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('EIP712Domain(string name,uint256 chainId,address verifyingContract)')); 11 | const SUSHISWAPV2PAIR_DOMAIN_SEPERATOR_HASH = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')); 12 | const BENTOBOX_HASH = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('BentoBox V1')); 13 | const SUSHISWAP_PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; 14 | export const MAX_VALUE_SHARE = 115792089237316195423570985008687907853269984665640564039457584007913129639934; 15 | export function getKashiApprovalHash( 16 | user, 17 | master, 18 | approved, 19 | nonce, 20 | ) { 21 | return ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode( 22 | ['bytes32', 'bytes32', 'address', 'address', 'bool', 'uint256'], 23 | [ 24 | APPROVAL_SIGNATURE_HASH, 25 | WARNING_MESSAGE_HASH, 26 | user, 27 | master, 28 | approved, 29 | nonce, 30 | ], 31 | )); 32 | } 33 | 34 | export function getKashiDomainSeperatorHash( 35 | chainId, 36 | address, 37 | ) { 38 | return ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode( 39 | ['string', 'string', 'string', 'uint256', 'address'], 40 | [ 41 | DOMAIN_SEPARATOR_SIGNATURE_HASH, 42 | BENTOBOX_HASH, 43 | chainId, 44 | address, 45 | ], 46 | )); 47 | } 48 | 49 | export function getUniSushiSwapV2PairDomainSeperatorHash( 50 | name, 51 | chainId, 52 | address, 53 | ) { 54 | return ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode( 55 | ['bytes32', 'bytes32', 'bytes32', 'uint', 'address'], 56 | [ 57 | SUSHISWAPV2PAIR_DOMAIN_SEPERATOR_HASH, 58 | ethers.utils.keccak256(ethers.utils.toUtf8Bytes(name)), 59 | ethers.utils.keccak256(ethers.utils.toUtf8Bytes('1')), 60 | chainId, 61 | address, 62 | ], 63 | )); 64 | } 65 | 66 | 67 | export function getUniSushiSwapV2ApprovalHash( 68 | owner, 69 | spender, 70 | value, 71 | nonce, 72 | deadline, 73 | ) { 74 | return ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode( 75 | ['bytes32', 'address', 'address', 'uint', 'uint', 'uint'], 76 | [ 77 | SUSHISWAP_PERMIT_TYPEHASH, 78 | owner, 79 | spender, 80 | value, 81 | nonce, 82 | deadline, 83 | ], 84 | )); 85 | } 86 | 87 | export function getMasterContractApprovalHash ( 88 | domainSeperatorHash, 89 | kashiApprovalHash, 90 | ) { 91 | return abi.soliditySHA3( 92 | ['string', 'bytes32', 'bytes32'], 93 | [ 94 | EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA, 95 | domainSeperatorHash, 96 | kashiApprovalHash, 97 | 98 | ], 99 | ); 100 | } 101 | 102 | export const stripHexPrefix = (str: string): string => { 103 | if (typeof str !== 'string') { 104 | throw new Error(`[stripHexPrefix] input must be type 'string', received ${typeof str}`); 105 | } 106 | 107 | return ethers.utils.isHexString(str) ? str.slice(2) : str; 108 | }; 109 | 110 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@bitgo/smart-contracts", 3 | "version": "2.4.0", 4 | "description": "A library to build Ethereum smart contract function calls.", 5 | "main": "dist/src/index.js", 6 | "types": "dist/types/src/index.d.ts", 7 | "browser": "dist/lib.js", 8 | "scripts": { 9 | "test": "mocha --exit -r ts-node/register --timeout 100000 --recursive 'test/**/*.ts'", 10 | "build": "npm run build-ts && webpack --config webpack.config.js", 11 | "build-ts": "tsc", 12 | "lint": "TIMING=1 eslint --ignore-pattern dist/ --ext .ts --cache .", 13 | "lint-fix": "TIMING=1 eslint --fix --ignore-pattern dist/ --ext .ts --cache .", 14 | "prepublishOnly": "npm run build" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/bitgo/smart-contracts.git" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/bitgo/smart-contracts/issues" 22 | }, 23 | "homepage": "https://github.com/bitgo/smart-contracts#readme", 24 | "dependencies": { 25 | "ethers": "4.0.48", 26 | "bignumber.js": "^9.0.1", 27 | "ethereumjs-abi": "0.6.8", 28 | "ethereumjs-util": "6.2.0", 29 | "tronweb": "^4.1.0" 30 | }, 31 | "devDependencies": { 32 | "@types/ethereumjs-abi": "0.6.3", 33 | "@types/expect": "24.3.0", 34 | "@types/mocha": "5.2.7", 35 | "@typescript-eslint/eslint-plugin": "^4.31.0", 36 | "@typescript-eslint/parser": "^4.31.0", 37 | "bitgo": "11.1.1", 38 | "eslint": "^7.32.0", 39 | "expect": "24.9.0", 40 | "mocha": "6.2.3", 41 | "stream-browserify": "^3.0.0", 42 | "ts-loader": "^9.2.6", 43 | "ts-node": "8.5.4", 44 | "typescript": "^4.4.3", 45 | "webpack": "^5.54.0", 46 | "webpack-cli": "^4.8.0", 47 | "webpack-node-externals": "^3.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/base/contracts/contractInstances.ts: -------------------------------------------------------------------------------- 1 | import { ensure, ensureExist } from '../../util/ensure'; 2 | import { Instance, InstanceImpl } from './contracts'; 3 | import { Method, MethodClass, MethodDefinition, MethodsClass, Methods } from '../methods/methods'; 4 | 5 | import EthAbiContracts from '../../../eth/abis'; 6 | import TrxAbiContracts from '../../../trx/abis'; 7 | 8 | import EthInstances from '../../../eth/config/instances.json'; 9 | import TrxInstances from '../../../trx/config/instances.json'; 10 | 11 | 12 | export const contracts = { eth: EthAbiContracts, trx: TrxAbiContracts }; 13 | export const instances = { eth: EthInstances, trx: TrxInstances }; 14 | 15 | /** 16 | * List the names of the available ABI definitions. 17 | * These are stored locally as JSON ABI definition files 18 | */ 19 | export function listContractTypes(chainName: string): string[] { 20 | return Object.keys(contracts[chainName]); 21 | } 22 | 23 | /** 24 | * Return specific ABI 25 | * @param contractName The name of the contract to read the ABI for 26 | * @param chainName The name of the chain to read the ABI for 27 | * @param accessAbiValues Access values to the ABI, some contracts has sub levels to access the ABI, e.g Tron has {"entrys" : [..ABI]} 28 | * 29 | */ 30 | export function getAbiContract(contractName: string, chainName: string, accessAbiValues : string[] = []) { 31 | let contract = contracts[chainName][contractName]; 32 | if (accessAbiValues) { 33 | accessAbiValues.forEach(field => { 34 | contract = contract[field]; 35 | }); 36 | } 37 | return ensureExist(contract, `Invalid JSON field`); 38 | } 39 | 40 | 41 | export class ContractReader> { 42 | protected readonly chainName: string; 43 | protected readonly defaultInstanceKey: string; 44 | private readonly methodsClass: MethodsClass; 45 | private readonly methodClass: MethodClass; 46 | 47 | constructor( 48 | chainName: string, 49 | defaultInstanceKey: string, 50 | methodsClass: MethodsClass, 51 | methodClass: MethodClass, 52 | ) { 53 | if (!chainName || !defaultInstanceKey) { 54 | throw new Error('Default chain params not defined.'); 55 | } 56 | this.chainName = chainName; 57 | this.defaultInstanceKey = defaultInstanceKey; 58 | this.methodsClass = methodsClass; 59 | this.methodClass = methodClass; 60 | } 61 | 62 | /** 63 | * Read in and parse config for instances of this contract type 64 | * @param contractName The name of the contract to read the config for 65 | * @param accessAbiValues Some contracts has sub levels to access the ABI, e.g Tron has {"entrys" : [..ABI]} 66 | */ 67 | readContractInstances(contractName: string, accessAbiValues : string[] = []): Instance[] { 68 | const instances = this.getInstances(contractName, this.chainName); 69 | const contract = this.getContract(contractName, listContractTypes(this.chainName), accessAbiValues); 70 | 71 | // Save them with the instance names lowercased, for easier lookup 72 | return this.parse(instances, contract); 73 | } 74 | 75 | 76 | /** 77 | * Return the contract specific ABI 78 | * @param contractName The name of the contract to 79 | * @param contractTypesList 80 | * @param accessAbiValues Access values to the ABI, some contracts has sub levels to access the ABI, e.g Tron has {"entrys" : [..ABI]} 81 | */ 82 | public getContract(contractName: string, contractTypesList: string[], accessAbiValues : string[] = []) { 83 | ensure(contractTypesList.includes(contractName), `Unknown contract: ${contractName}`); 84 | return getAbiContract(contractName, this.chainName, accessAbiValues); 85 | } 86 | 87 | private getInstances(contractName: string, chainName: string) { 88 | const config = instances[chainName]; 89 | ensure(config[contractName], `Unknown contract: ${contractName}`); 90 | return config[contractName]; 91 | } 92 | 93 | private parse(parsedConfig: {[key: string]: string}, contract: MethodDefinition[]): Instance[] { 94 | const methodList: TMethod[] = this.parseMethods(contract); 95 | const result: Instance[] = []; 96 | 97 | Object.keys(parsedConfig).forEach((instanceName: string) => { 98 | const address: string = parsedConfig[instanceName]; 99 | result.push(new InstanceImpl(instanceName.toLowerCase(), new this.methodsClass(methodList), address)); 100 | }); 101 | 102 | // If no exists a default intance create one 103 | if (!Object.keys(parsedConfig).some((instanceName: string) => instanceName === 'default')) { 104 | result.push(new InstanceImpl('default', new this.methodsClass(methodList))); 105 | } 106 | return result; 107 | } 108 | 109 | private parseMethods(definitions: MethodDefinition[]): TMethod[] { 110 | return definitions.reduce((collector: TMethod[], def: MethodDefinition) => { 111 | const method: TMethod = new this.methodClass(def); 112 | collector.push(method); 113 | return collector; 114 | }, []); 115 | } 116 | } 117 | 118 | export interface ContractInstance { 119 | [key: string]: string; 120 | } 121 | -------------------------------------------------------------------------------- /src/base/contracts/contracts.ts: -------------------------------------------------------------------------------- 1 | import { BaseMethodContainerMap, Method, MethodDefinition, Methods } from '../methods/methods'; 2 | 3 | /** 4 | * This defines the base abstraction of contracts 5 | */ 6 | export interface Contract { 7 | name: string; 8 | instance(name?: string): Instance>; 9 | listMethods(): MethodDefinition[]; 10 | } 11 | 12 | /** 13 | * This represents the concrete contract on the network 14 | */ 15 | export interface Instance> { 16 | name: string; 17 | address?: string; 18 | methodsHandler: TMethods 19 | 20 | methods(): BaseMethodContainerMap; 21 | explain(): MethodDefinition[]; 22 | } 23 | 24 | export class InstanceImpl> implements Instance { 25 | name: string; 26 | address?: string; 27 | methodsHandler: TMethods; 28 | 29 | constructor(name: string, methodsHandler: TMethods, address?: string) { 30 | this.name = name; 31 | this.address = address; 32 | this.methodsHandler = methodsHandler; 33 | } 34 | 35 | methods(): BaseMethodContainerMap { 36 | return this.methodsHandler.container; 37 | } 38 | 39 | explain(): MethodDefinition[] { 40 | return this.methodsHandler.explain(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/base/decoder/decoder.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface Decoder { 3 | decode(data: Buffer | string): TCallExplanation; 4 | } 5 | 6 | export interface CallExplanation { 7 | methodId: string; 8 | contractName: string; 9 | name: string; 10 | } 11 | 12 | export interface FunctionCallExplanation extends CallExplanation { 13 | args: any[]; 14 | } 15 | -------------------------------------------------------------------------------- /src/base/decoder/types.ts: -------------------------------------------------------------------------------- 1 | import { bufferToInt } from 'ethereumjs-util'; 2 | import { ensure } from '../../util/ensure'; 3 | 4 | 5 | export enum Primitive { 6 | Address, 7 | Bool, 8 | String, 9 | Bytes, 10 | Int, 11 | } 12 | 13 | export function formatBool(value: Buffer): boolean { 14 | const intBool = bufferToInt(value); 15 | return intBool === 1; 16 | } 17 | 18 | export function isArray (type: string): boolean { 19 | return type.includes('[]') && type.lastIndexOf(']') === type.length - 1; 20 | } 21 | 22 | export function isHex(data: string): boolean { 23 | return /^([0-9a-f])+$/.test(data); 24 | } 25 | 26 | /** 27 | * Take an array type and return the subtype that it is an array of 28 | * i.e. uint256[][] would return uint256[], and uint256[] would return uint256 29 | * @param type The type to parse subarray from 30 | * @return The subarray type 31 | */ 32 | export function parseArraySubType(type: string): string { 33 | ensure(isArray(type), 'Invalid type, not an array'); 34 | return type.slice(0, type.lastIndexOf('[')); 35 | } 36 | 37 | 38 | /** 39 | * Take a type string, such as uint256, and return the primitive value type that it represents 40 | * @param type The type to parse 41 | * @return The primitive value type 42 | * @throws if the type is unknown 43 | */ 44 | export function parsePrimitive(type: string): Primitive { 45 | if (type.includes('address')) { 46 | return Primitive.Address; 47 | } 48 | 49 | if (type.includes('bool')) { 50 | return Primitive.Bool; 51 | } 52 | 53 | if (type.includes('string')) { 54 | return Primitive.String; 55 | } 56 | 57 | if (type.includes('bytes')) { 58 | return Primitive.Bytes; 59 | } 60 | 61 | if (type.includes('int')) { 62 | return Primitive.Int; 63 | } 64 | 65 | throw new Error(`Unknown type ${type}`); 66 | } 67 | -------------------------------------------------------------------------------- /src/base/factory.ts: -------------------------------------------------------------------------------- 1 | import { Contract } from './contracts/contracts'; 2 | import { Decoder } from './decoder/decoder'; 3 | 4 | /** 5 | * This gives the user the ability to get contract and decoder instances for each supported chain 6 | */ 7 | export interface Factory, TDecoder extends Decoder> { 8 | getContract(name: string): TContract; 9 | getDecoder(): TDecoder; 10 | listContractTypes(): string[]; 11 | } 12 | -------------------------------------------------------------------------------- /src/base/methods/methods.ts: -------------------------------------------------------------------------------- 1 | export type MethodsClass> = new(methods: TMethod[]) => TMethods; 2 | export type MethodClass = new(...args: any[]) => TMethod; 3 | 4 | export interface Parameter { 5 | components: any; 6 | name: string 7 | type: string; 8 | } 9 | 10 | export interface MethodDefinition { 11 | name: string, 12 | type: string; 13 | } 14 | 15 | export interface MethodResponse { 16 | data: string; 17 | } 18 | 19 | export interface Method { 20 | id: string; 21 | name: string; 22 | call(params: { [key: string]: any }): any; 23 | explain(): MethodDefinition; 24 | } 25 | 26 | /** 27 | * This represents the set of methods that conform a contract instance 28 | */ 29 | export interface Methods { 30 | container: BaseMethodContainerMap; 31 | 32 | explain(): MethodDefinition[]; 33 | } 34 | 35 | export class MethodsImpl implements Methods { 36 | container: BaseMethodContainerMap; 37 | 38 | constructor(methodAbis: TMethod[]) { 39 | this.container = this.parse(methodAbis); 40 | } 41 | 42 | explain(): MethodDefinition[] { 43 | return Object.keys(this.container).map((name: string) => this.container[name].explain()); 44 | } 45 | 46 | private parse(methods: TMethod[]): BaseMethodContainerMap { 47 | return methods.reduce((collector: BaseMethodContainerMap, method: TMethod) => { 48 | collector[method.name] = method; 49 | return collector; 50 | }, {}); 51 | } 52 | } 53 | 54 | export interface BaseMethodContainerMap { 55 | [key: string]: TMethod; 56 | } 57 | -------------------------------------------------------------------------------- /src/eth/contracts/contracts.ts: -------------------------------------------------------------------------------- 1 | import { EthMethod } from '../methods/methods'; 2 | import { ContractReader } from '../../base/contracts/contractInstances'; 3 | import { ensureExist } from '../../util/ensure'; 4 | import { Contract, Instance } from '../../base/contracts/contracts'; 5 | import { MethodDefinition, Methods, MethodsImpl } from '../../base/methods/methods'; 6 | 7 | export class EthContract implements Contract { 8 | static readonly chainName = 'eth'; 9 | private readonly DEFAULT_INSTANCE_KEY = 'default'; 10 | contractInstances: Instance>[]; 11 | contractReader: ContractReader>; 12 | 13 | constructor(readonly name: string) { 14 | this.contractReader = new ContractReader>(EthContract.chainName, this.DEFAULT_INSTANCE_KEY, MethodsImpl, EthMethod); 16 | this.contractInstances = this.contractReader.readContractInstances(name); 17 | } 18 | 19 | instance(name?: string): Instance> { 20 | name = name ? name.toLowerCase() : this.DEFAULT_INSTANCE_KEY; 21 | const instance = this.contractInstances.find((i) => i.name === name); 22 | return ensureExist(instance, `Unknown instance: ${name}`); 23 | } 24 | 25 | listMethods(): MethodDefinition[] { 26 | return this.instance().explain().filter(method => method.type === 'function'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/eth/decoder/decoder.ts: -------------------------------------------------------------------------------- 1 | import { methodID, rawDecode } from 'ethereumjs-abi'; 2 | import { bufferToHex } from 'ethereumjs-util'; 3 | import { Decoder, FunctionCallExplanation } from '../../base/decoder/decoder'; 4 | import { formatValue } from './types'; 5 | import { ensure } from '../../util/ensure'; 6 | import { EthMethod } from '../methods/methods'; 7 | import { listContractTypes, contracts } from '../../base/contracts/contractInstances'; 8 | import { EthContract } from '../contracts/contracts'; 9 | import { parseToBuffer } from '../../../src/util/string'; 10 | 11 | export interface MethodData { 12 | abi: EthMethod; 13 | contractName: string; 14 | } 15 | 16 | export interface MethodIdMapping { 17 | [key: string]: MethodData; 18 | } 19 | 20 | 21 | export class EthDecoder implements Decoder { 22 | private loadMethods(): MethodIdMapping { 23 | const result: MethodIdMapping = {}; 24 | 25 | for (const contractName of listContractTypes(EthContract.chainName)) { 26 | const abi = contracts[EthContract.chainName][contractName]; 27 | 28 | for (const methodAbi of abi) { 29 | if (methodAbi.inputs) { 30 | const name = methodAbi.name; 31 | const types = methodAbi.inputs.map((input: { type: any; }) => input.type); 32 | const methodIdString = bufferToHex(methodID(name, types)); 33 | 34 | result[methodIdString] = { contractName, abi: methodAbi }; 35 | } 36 | } 37 | 38 | } 39 | return result; 40 | } 41 | 42 | constructor() { 43 | this.methodsById = this.loadMethods(); 44 | } 45 | 46 | protected readonly methodsById: MethodIdMapping; 47 | 48 | public decode(data: Buffer | string): FunctionCallExplanation { 49 | if (typeof data === 'string') { 50 | data = parseToBuffer(data); 51 | } 52 | 53 | const methodId = bufferToHex(data.slice(0, 4)); 54 | const abiEncodedArguments = data.slice(4); 55 | ensure(this.methodsById[methodId], `Unknown method: ${methodId}`); 56 | 57 | const { contractName, abi: { name, inputs } } = this.methodsById[methodId]; 58 | const types = inputs.map((input) => input.type); 59 | 60 | const decodedArguments = rawDecode(types, abiEncodedArguments); 61 | 62 | const args: any[] = []; 63 | for (let i = 0; i < inputs.length; i++) { 64 | const { name, type } = inputs[i]; 65 | const decodedArgument = decodedArguments[i]; 66 | args.push({ name, type, value: formatValue(decodedArgument, type) }); 67 | } 68 | 69 | return { 70 | methodId, 71 | name, 72 | args, 73 | contractName, 74 | }; 75 | } 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/eth/decoder/types.ts: -------------------------------------------------------------------------------- 1 | import { addHexPrefix, bufferToHex } from 'ethereumjs-util'; 2 | import { formatBool, isArray, parseArraySubType, parsePrimitive, Primitive } from '../../base/decoder/types'; 3 | import { BigNumber } from 'bignumber.js'; 4 | 5 | function formatArray(values: any[], subtype: string): any[] { 6 | return values.map((value) => formatValue(value, subtype)); 7 | } 8 | 9 | /** 10 | * Format values of different types 11 | * @param value The value to format 12 | * @param type The solidity type string of the value 13 | * @return The formatted value 14 | */ 15 | export function formatValue(value: any, type: string): any { 16 | if (isArray(type)) { 17 | return formatArray(value, parseArraySubType(type)); 18 | } else { 19 | switch (parsePrimitive(type)) { 20 | case Primitive.Address: 21 | return addHexPrefix(value); 22 | case Primitive.Bool: 23 | return formatBool(value); 24 | case Primitive.Bytes: 25 | return bufferToHex(value); 26 | case Primitive.Int: 27 | // value is a Buffer 28 | const bigNumberValue = new BigNumber(value.toString('hex'), 16); 29 | return bigNumberValue.toFixed(); 30 | case Primitive.String: 31 | return value.toString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/eth/factory.ts: -------------------------------------------------------------------------------- 1 | import { EthContract } from './contracts/contracts'; 2 | import { listContractTypes } from '../base/contracts/contractInstances'; 3 | 4 | import { EthDecoder } from './decoder/decoder'; 5 | import { Factory } from '../base/factory'; 6 | 7 | export class EthFactory implements Factory { 8 | getContract(name: string): EthContract { 9 | return new EthContract(name); 10 | } 11 | 12 | getDecoder(): EthDecoder { 13 | return new EthDecoder(); 14 | } 15 | 16 | listContractTypes(): string[] { 17 | return listContractTypes(EthContract.chainName); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/eth/methods/methods.ts: -------------------------------------------------------------------------------- 1 | import * as abi from 'ethereumjs-abi'; 2 | import { ensure } from '../../util/ensure'; 3 | import * as ethUtil from 'ethereumjs-util'; 4 | import { Method, MethodDefinition, Parameter } from '../../base/methods/methods'; 5 | import * as ethers from 'ethers'; 6 | export interface EthMethodDefinition extends MethodDefinition { 7 | constant: boolean; 8 | payable: boolean; 9 | inputs: Parameter[]; 10 | outputs?: Parameter[]; 11 | } 12 | 13 | export class EthMethod implements Method { 14 | private _id: string; 15 | constant: boolean; 16 | payable: boolean; 17 | inputs: Parameter[]; 18 | outputs?: Parameter[]; 19 | name: string; 20 | type: string; 21 | get id(): string { 22 | if (!this._id) { 23 | this._id = abi.methodID(this.name, this.inputs.map((input) => input.type)).toString('hex'); 24 | } 25 | return this._id; 26 | } 27 | 28 | constructor(definitions: {[key:string]: any}) { 29 | const { constant, payable, inputs, outputs, name, type } = definitions; 30 | this.constant = constant; 31 | this.payable = payable; 32 | this.inputs = inputs; 33 | this.outputs = outputs; 34 | this.name = name; 35 | this.type = type; 36 | } 37 | 38 | call(params: { [key: string]: any }): any { 39 | const types: string[] = []; 40 | const values: string[] = []; 41 | let data = ''; 42 | this.inputs.forEach((input) => { 43 | if (Array.isArray(input.components)) { 44 | let tuple = 'tuple('; 45 | input.components.forEach(component => { 46 | ensure(params[component.name] !== undefined, `Missing required parameter: ${component.name}`); 47 | tuple += component.type + ','; 48 | values.push(params[component.name]); 49 | }); 50 | tuple = tuple.slice(0, -1); 51 | tuple += ')'; 52 | 53 | types.push(tuple); 54 | const abiElement = 'function ' + this.name + '(' + tuple + ')'; 55 | const iface = new ethers.utils.Interface([abiElement]); 56 | const methodId = iface.functions[this.name].sighash; 57 | data = methodId + ethers.utils.defaultAbiCoder.encode(types, [values]).slice(2); 58 | 59 | } else { 60 | ensure(params[input.name] !== undefined, `Missing required parameter: ${input.name}`); 61 | values.push(params[input.name]); 62 | types.push(input.type); 63 | data = ethUtil.addHexPrefix(this.id + abi.rawEncode(types, values).toString('hex')); 64 | 65 | } 66 | 67 | }); 68 | 69 | return { 70 | data, 71 | amount: '0', 72 | }; 73 | } 74 | 75 | explain(): EthMethodDefinition { 76 | return { 77 | name: this.name, 78 | type: this.type, 79 | constant: this.constant, 80 | payable: this.payable, 81 | inputs: this.inputs, 82 | outputs: this.outputs, 83 | }; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Decoder, FunctionCallExplanation } from './base/decoder/decoder'; 2 | import { Contract } from './base/contracts/contracts'; 3 | import { Method } from './base/methods/methods'; 4 | import { EthFactory } from './eth/factory'; 5 | import { TrxFactory } from './trx/factory'; 6 | import { Factory } from './base/factory'; 7 | 8 | 9 | const factoryMap : any = { 10 | eth: EthFactory, 11 | trx: TrxFactory, 12 | }; 13 | 14 | /** 15 | * Get the list of coin tickers supported by this library. 16 | */ 17 | export const supportedCoins = Object.keys(factoryMap); 18 | 19 | /** 20 | * Get a transaction builder for the given coin. 21 | * 22 | * @param chainName One of the {@code supportedCoins} 23 | * @returns An instance of a {@code TransactionBuilder} 24 | */ 25 | export function getContractsFactory(chainName: string): Factory, Decoder> { 26 | const factoryClass = factoryMap[chainName]; 27 | if (!factoryClass) { 28 | throw new Error(`Coin ${chainName} not supported`); 29 | } 30 | 31 | return new factoryClass(); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/trx/contracts/contracts.ts: -------------------------------------------------------------------------------- 1 | import { TrxMethod } from '../methods/methods'; 2 | import { ContractReader } from '../../base/contracts/contractInstances'; 3 | import { ensureExist } from '../../util/ensure'; 4 | import { Contract, Instance } from '../../base/contracts/contracts'; 5 | import { MethodDefinition, Methods, MethodsImpl } from '../../base/methods/methods'; 6 | 7 | export class TrxContract implements Contract { 8 | static readonly chainName = 'trx'; 9 | private readonly DEFAULT_INSTANCE_KEY = 'default'; 10 | static readonly ACCESS_ABI_VALUES = ['entrys']; 11 | _contractInstances: Instance>[]; 12 | _contractReader: ContractReader>; 13 | 14 | constructor(readonly name: string) { 15 | this._contractReader = new ContractReader>(TrxContract.chainName, this.DEFAULT_INSTANCE_KEY, MethodsImpl, TrxMethod); 17 | this._contractInstances = this._contractReader.readContractInstances(name, TrxContract.ACCESS_ABI_VALUES ); 18 | } 19 | 20 | instance(name?: string): Instance> { 21 | name = name ? name.toLowerCase() : this.DEFAULT_INSTANCE_KEY; 22 | const instance = this._contractInstances.find((i) => i.name === name); 23 | return ensureExist(instance, `Unknown instance: ${name}`); 24 | } 25 | 26 | listMethods(): MethodDefinition[] { 27 | return this.instance().explain().filter(method => method.type === 'Function'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/trx/decoder/decoder.ts: -------------------------------------------------------------------------------- 1 | import { methodID } from 'ethereumjs-abi'; 2 | import { bufferToHex } from 'ethereumjs-util'; 3 | import { Decoder, FunctionCallExplanation } from '../../base/decoder/decoder'; 4 | import { formatValue } from './types'; 5 | import { ensure } from '../../util/ensure'; 6 | import { TrxMethod } from '../methods/methods'; 7 | import { getAbiContract, listContractTypes } from '../../base/contracts/contractInstances'; 8 | import { TrxContract } from '../contracts/contracts'; 9 | import { parseToBuffer } from '../../../src/util/string'; 10 | // TronWeb does not use ES Modules so we must use require 11 | const TronWeb = require('tronweb'); 12 | 13 | 14 | export interface MethodData { 15 | abi: TrxMethod; 16 | contractName: string; 17 | } 18 | 19 | export interface MethodIdMapping { 20 | [key: string]: MethodData; 21 | } 22 | 23 | 24 | export class TrxDecoder implements Decoder { 25 | private loadMethods(): MethodIdMapping { 26 | const result: MethodIdMapping = {}; 27 | 28 | for (const contractName of listContractTypes(TrxContract.chainName)) { 29 | const jsonTronAbi = getAbiContract(contractName, TrxContract.chainName, TrxContract.ACCESS_ABI_VALUES); 30 | 31 | for (const methodAbi of jsonTronAbi) { 32 | if (methodAbi.type === 'Function') { 33 | const name = methodAbi.name; 34 | methodAbi.inputs = methodAbi.inputs ? methodAbi.inputs : []; 35 | const types = methodAbi.inputs.map((input: { type: any; }) => input.type); 36 | const methodIdString = bufferToHex(methodID(name, types)); 37 | 38 | result[methodIdString] = { contractName, abi: methodAbi }; 39 | } 40 | } 41 | } 42 | return result; 43 | } 44 | 45 | constructor() { 46 | this.methodsById = this.loadMethods(); 47 | } 48 | 49 | protected readonly methodsById: MethodIdMapping; 50 | 51 | 52 | public decode(data: Buffer | string ): FunctionCallExplanation { 53 | if (typeof data === 'string') { 54 | data = parseToBuffer(data); 55 | } 56 | const methodId = bufferToHex(data.slice(0, 4)); 57 | ensure(this.methodsById[methodId], `Unknown method: ${methodId}`); 58 | 59 | const { contractName, abi: { name, inputs } } = this.methodsById[methodId]; 60 | const names = inputs.map(({ name }) => name).filter(name => !!name); 61 | const types = inputs.map(({ type }) => type); 62 | 63 | const abiEncodedArgs = bufferToHex(data); 64 | const decodedArguments = TronWeb.utils.abi.decodeParams(names, types, abiEncodedArgs, true); 65 | 66 | const args: any[] = []; 67 | for (let i = 0; i < inputs.length; i++) { 68 | const { name, type } = inputs[i]; 69 | const decodedArgument = decodedArguments[name]; 70 | args.push({ name, type, value: formatValue(decodedArgument, type) }); 71 | } 72 | 73 | return { 74 | methodId, 75 | name, 76 | args, 77 | contractName, 78 | }; 79 | } 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/trx/decoder/types.ts: -------------------------------------------------------------------------------- 1 | import { bufferToHex } from 'ethereumjs-util'; 2 | import { formatBool, isArray, parseArraySubType, parsePrimitive, Primitive } from '../../base/decoder/types'; 3 | import { BigNumber } from 'bignumber.js'; 4 | // TronWeb does not use ES Modules so we must use require 5 | const TronWeb = require('tronweb'); 6 | 7 | function formatArray(values: any[], subtype: string): any[] { 8 | return values.map((value) => formatValue(value, subtype)); 9 | } 10 | 11 | /** 12 | * Format values of different types 13 | * @param value The value to format 14 | * @param type The solidity type string of the value 15 | * @return The formatted value 16 | */ 17 | export function formatValue(value: any, type: string): any { 18 | if (isArray(type)) { 19 | return formatArray(value, parseArraySubType(type)); 20 | } else { 21 | switch (parsePrimitive(type)) { 22 | case Primitive.Address: 23 | return TronWeb.address.fromHex(value); 24 | case Primitive.Bool: 25 | return formatBool(value); 26 | case Primitive.Bytes: 27 | return bufferToHex(value); 28 | case Primitive.Int: 29 | const bigNumberValue = new BigNumber(value._hex.toString('hex'), 16); 30 | return bigNumberValue.toFixed(); 31 | case Primitive.String: 32 | return value.toString(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/trx/factory.ts: -------------------------------------------------------------------------------- 1 | import { TrxContract } from './contracts/contracts'; 2 | import { listContractTypes } from '../base/contracts/contractInstances'; 3 | 4 | import { TrxDecoder } from './decoder/decoder'; 5 | import { Factory } from '../base/factory'; 6 | 7 | export class TrxFactory implements Factory { 8 | getContract(name: string): TrxContract { 9 | return new TrxContract(name); 10 | } 11 | 12 | getDecoder(): TrxDecoder { 13 | return new TrxDecoder(); 14 | } 15 | 16 | listContractTypes(): string[] { 17 | return listContractTypes(TrxContract.chainName); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/trx/methods/methods.ts: -------------------------------------------------------------------------------- 1 | import * as abi from 'ethereumjs-abi'; 2 | import { ensure } from '../../util/ensure'; 3 | import * as ethUtil from 'ethereumjs-util'; 4 | import { Method, MethodDefinition, Parameter } from '../../base/methods/methods'; 5 | // TronWeb does not use ES Modules so we must use require 6 | const TronWeb = require('tronweb'); 7 | 8 | export interface TrxMethodDefinition extends MethodDefinition { 9 | constant?: boolean; 10 | payable?: boolean; 11 | inputs?: Parameter[]; 12 | outputs?: Parameter[]; 13 | } 14 | 15 | export class TrxMethod implements Method { 16 | private _id: string; 17 | constant?: boolean; 18 | payable?: boolean; 19 | inputs: Parameter[]; 20 | outputs?: Parameter[]; 21 | name: string; 22 | type: string; 23 | get id(): string { 24 | if (!this._id) { 25 | this._id = abi.methodID(this.name, this.inputs.map((input) => input.type)).toString('hex'); 26 | } 27 | return this._id; 28 | } 29 | 30 | constructor(definitions: {[key:string]: any}) { 31 | const { constant, payable, inputs, outputs, name, type } = definitions; 32 | this.constant = constant; 33 | this.payable = payable; 34 | this.inputs = inputs || []; 35 | this.outputs = outputs; 36 | this.name = name; 37 | this.type = type; 38 | } 39 | 40 | call(params: { [key: string]: any }): any { 41 | const types: string[] = []; 42 | const values: string[] = []; 43 | this.inputs.forEach((input: Parameter) => { 44 | ensure(params[input.name] !== undefined, `Missing required parameter: ${input.name}`); 45 | values.push(params[input.name]); 46 | types.push(input.type); 47 | }); 48 | 49 | const tronEncoded = TronWeb.utils.abi.encodeParams(types, values); 50 | const ENCODED_PREFIX_REGEX = /^(0x)/; 51 | const dataEncoded = ethUtil.addHexPrefix(this.id + tronEncoded.replace(ENCODED_PREFIX_REGEX, '')); 52 | return { 53 | data: dataEncoded, 54 | amount: '0', 55 | }; 56 | } 57 | 58 | explain(): TrxMethodDefinition { 59 | return { 60 | name: this.name, 61 | type: this.type, 62 | constant: this.constant, 63 | payable: this.payable, 64 | inputs: this.inputs, 65 | outputs: this.outputs, 66 | }; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/util/ensure.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if `test` is truthy. If it is not, then throw with the given message 3 | * @param test The object to check for truthiness 4 | * @param msg The message to throw if `test` is falsy 5 | */ 6 | export function ensure(test: any, msg: string): void { 7 | if (!test) { 8 | throw new Error(msg); 9 | } 10 | } 11 | 12 | export function ensureExist(element: T | undefined, msg: string): T { 13 | if (!element) { 14 | throw new Error(msg); 15 | } 16 | return element; 17 | } 18 | -------------------------------------------------------------------------------- /src/util/string.ts: -------------------------------------------------------------------------------- 1 | import { isHex } from '../base/decoder/types'; 2 | 3 | export function stripHexPrefix(data: string): string { 4 | if (data.startsWith('0x')) { 5 | return data.slice(2); 6 | } 7 | return data; 8 | } 9 | 10 | export function parseToBuffer(data: string): Buffer { 11 | let bufferData : Buffer; 12 | data = stripHexPrefix(data); 13 | if (isHex(data)) { 14 | bufferData = Buffer.from(data, 'hex'); 15 | } else { 16 | throw new Error('String data is not on hex format'); 17 | } 18 | return bufferData; 19 | } 20 | -------------------------------------------------------------------------------- /test/chain/base/factory.test.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory, supportedCoins } from '../../../src'; 2 | const expect = require('expect'); 3 | 4 | describe('Factory tests', () => { 5 | 6 | it('Should create an factory instance for each supported chain', () => { 7 | supportedCoins.forEach(chainName => { 8 | const contract = getContractsFactory(chainName); 9 | expect(contract).toBeDefined(); 10 | }); 11 | }); 12 | 13 | it('Should fail to create an factory instance for unsupported chain', () => { 14 | expect(() => getContractsFactory('unsupportedChain')).toThrowError('Coin unsupportedChain not supported'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/chain/eth/contract.test.ts: -------------------------------------------------------------------------------- 1 | const expect = require('expect'); // tslint:disable-line 2 | import * as fs from 'fs'; 3 | import { Contract } from '../../../src/base/contracts/contracts'; 4 | import { MethodDefinition } from '../../../src/base/methods/methods'; 5 | import { EthContract } from '../../../src/eth/contracts/contracts'; 6 | import { EthMethodDefinition } from '../../../src/eth/methods/methods'; 7 | import { ContractInstance } from '../../../src/base/contracts/contractInstances'; 8 | import { getContractsFactory } from '../../../src'; 9 | import { getKnownSolidityTypes, getSolidityParameter, testFuzzedContractMethods } from '../../testutil'; 10 | 11 | describe('Contract', () => { 12 | const chainName = 'eth'; 13 | const ethContracts = getContractsFactory(chainName); 14 | 15 | describe('Test Contracts ABIs', () => { 16 | 17 | let instanceConfig: { [key: string]: ContractInstance }; 18 | 19 | before(() => { 20 | instanceConfig = JSON.parse(fs.readFileSync('eth/config/instances.json', 'utf-8')); 21 | }); 22 | 23 | /** 24 | * Run `callback` on every contract that we have defined locally 25 | * @param callback Function with tests to run on each contract 26 | */ 27 | const testStaticContracts = (callback: (contract: Contract, instanceName?: string) => void) => { 28 | ethContracts.listContractTypes().forEach((abiFileName) => { 29 | callback(ethContracts.getContract(abiFileName)); 30 | }); 31 | }; 32 | 33 | it('Should fail to instantiate an unknown contract name', () => { 34 | const unknownContractName = 'FakeContractType'; 35 | expect(() => new EthContract(unknownContractName)).toThrow(`Unknown contract: ${unknownContractName}`); 36 | }); 37 | 38 | 39 | testStaticContracts((contract: Contract) => { 40 | describe(`${contract.name}`, () => { 41 | const getRandomInstanceName = () => { 42 | const potentialInstances = instanceConfig[contract.name]; 43 | const instanceIndex = Math.floor(Math.random() * Object.keys(potentialInstances).length); 44 | return Object.keys(potentialInstances)[instanceIndex]; 45 | }; 46 | 47 | it('Should instantiate correctly', () => { 48 | expect(contract).toBeDefined(); 49 | }); 50 | 51 | it('Should fail to instantiate an unknown instance name', () => { 52 | const unknownInstanceName = 'fakeinstance'; 53 | expect(() => contract.instance(unknownInstanceName)).toThrow(`Unknown instance: ${unknownInstanceName}`); 54 | }); 55 | 56 | 57 | it('Should fail when given no parameters to a function that requires them', () => { 58 | // Since methods can overload each other we have to double check that it actually has only no params 59 | const methodsWithoutParameters: Set = new Set(); 60 | const methodsWithParameters: MethodDefinition[] = contract.listMethods() 61 | .filter((method: MethodDefinition) => { 62 | // TODO(STLX-1617): Fix returned MethodDefinition type for each chain 63 | const castedMethod = method as EthMethodDefinition; 64 | const noParams = castedMethod.inputs.length === 0; 65 | if (noParams) { 66 | methodsWithoutParameters.add(castedMethod.name); 67 | } 68 | return !noParams; 69 | }) 70 | .filter((method: MethodDefinition) => !methodsWithoutParameters.has(method.name)); 71 | 72 | methodsWithParameters.forEach((method: MethodDefinition) => { 73 | expect(() => contract.instance().methods()[method.name].call({})).toThrow('Missing required parameter'); 74 | }); 75 | }); 76 | 77 | it('Should succeed when given parameters to a function that doesnt require them', () => { 78 | const methodsWithoutParameters = contract.listMethods() 79 | .filter((method: any) => method.inputs.length === 0); 80 | 81 | methodsWithoutParameters.forEach((method: MethodDefinition) => { 82 | getKnownSolidityTypes(chainName).forEach((type) => { 83 | const { data } = contract.instance().methods()[method.name].call({ unexpectedParam: getSolidityParameter(chainName, type) }); 84 | expect(data).toBeDefined(); 85 | }); 86 | }); 87 | }); 88 | 89 | it('Should succeed when given expected parameters', () => { 90 | testFuzzedContractMethods(chainName, contract, ({ data }) => { 91 | expect(data).toBeDefined(); 92 | }); 93 | }); 94 | 95 | it('Should succeed with custom address instances', () => { 96 | const instanceAddress = getSolidityParameter(chainName, 'address'); 97 | testFuzzedContractMethods(chainName, contract, ({ data }) => { 98 | expect(data).toBeDefined(); 99 | }, { address: instanceAddress }); 100 | }); 101 | 102 | it('Should succeed with instances referenced by name', () => { 103 | const instanceName = getRandomInstanceName(); 104 | if (instanceName) { 105 | // const instanceAddress = instanceConfig[contract.name][instanceName]; 106 | testFuzzedContractMethods(chainName, contract, ({ data }) => { 107 | expect(data).toBeDefined(); 108 | }, { instanceName }); 109 | } 110 | }); 111 | }); 112 | }); 113 | }); 114 | describe('Eth Contracts using factory method', () => { 115 | let supportedEthContracts: string[]; 116 | 117 | before(() => { 118 | supportedEthContracts = ethContracts.listContractTypes(); 119 | }); 120 | 121 | it('Should create a valid contract instance for each supported eth contract', () => { 122 | supportedEthContracts.forEach(contract => { 123 | const contractInstance = ethContracts.getContract(contract); 124 | expect(contractInstance).toHaveProperty('name'); 125 | expect(contractInstance).toHaveProperty('contractReader'); 126 | expect(contractInstance).toHaveProperty('contractInstances'); 127 | expect(contractInstance.name).toEqual(contract); 128 | }); 129 | }); 130 | 131 | it('Should fail to create a unknown token instance', () => { 132 | const contractName = 'StandardERC20'; 133 | const tokenName = 'invalid'; 134 | expect(() => ethContracts.getContract(contractName).instance(tokenName)).toThrowError(`Unknown instance: ${tokenName}`); 135 | }); 136 | 137 | it('Should exists a default instance for each eth contract type', () => { 138 | ethContracts.listContractTypes().forEach((contractName) => { 139 | const contractInstance = ethContracts.getContract(contractName).instance(); 140 | expect(contractInstance).toHaveProperty('name'); 141 | expect(contractInstance).toHaveProperty('address'); 142 | expect(contractInstance.name).toEqual('default'); 143 | }); 144 | }); 145 | 146 | it('Should call successfully an existing method in a contract', () => { 147 | const contractName = 'StandardERC20'; 148 | const tokenName = 'DAI'; 149 | const recipient = '0xadd62287c10d90f65fd3bf8bf94183df115c030a'; 150 | const tokenAmount = 1e18; // 1 DAI 151 | const daiContract = ethContracts.getContract(contractName).instance(tokenName); 152 | const callMethodResponse = daiContract.methods().approve.call({ _spender: recipient, _value: tokenAmount.toString(10) }); 153 | expect(daiContract).toHaveProperty('address'); 154 | expect(callMethodResponse).toHaveProperty('data'); 155 | expect(callMethodResponse).toHaveProperty('amount'); 156 | }); 157 | 158 | }); 159 | }); 160 | -------------------------------------------------------------------------------- /test/chain/eth/decoder.test.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src'; 2 | import { Decoder, FunctionCallExplanation } from '../../../src/base/decoder/decoder'; 3 | import { stripHexPrefix } from '../../../src/util/string'; 4 | const expect = require('expect'); 5 | 6 | interface TestCase { 7 | data: string; 8 | expected: FunctionCallExplanation; 9 | } 10 | 11 | const testCases: TestCase[] = [ 12 | { 13 | data: '0xa9059cbb00000000000000000000000010d4f942617a231eb1430c88fe43c8c2050437d90000000000000000000000000000000000000000000000000000000000002710', 14 | expected: { 15 | contractName: 'WrappedToken', 16 | name: 'transfer', 17 | methodId: '0xa9059cbb', 18 | args: [ 19 | { name: '_to', type: 'address', value: '0x10d4f942617a231eb1430c88fe43c8c2050437d9' }, 20 | { name: '_value', type: 'uint256', value: '10000' }, 21 | ], 22 | }, 23 | }, 24 | { 25 | data: '0xc2998238000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004ddc2d193948926d02f9b1fe9e1daa0718270ed5', 26 | expected: { 27 | contractName: 'CompoundComptroller', 28 | name: 'enterMarkets', 29 | methodId: '0xc2998238', 30 | args: [ 31 | { name: 'cTokens', type: 'address[]', value: ['0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5'] }, 32 | ], 33 | }, 34 | }, 35 | { 36 | data: '0xeb0dff66000000000000000000000000f7aba9b064a12330a00eafaa930e2fe8e76e65f0', 37 | expected: { 38 | contractName: 'DsrManager', 39 | name: 'exitAll', 40 | methodId: '0xeb0dff66', 41 | args: [ 42 | { name: 'dst', type: 'address', value: '0xf7aba9b064a12330a00eafaa930e2fe8e76e65f0' }, 43 | ], 44 | }, 45 | }, 46 | { 47 | data: '0x39125215000000000000000000000000b19fb72b55f5374a062ddcba874e566b1d93f5d3000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005f7cde11000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000416508bd6fc3da79ff7e5b84ff79f50e48112579d7b5190caeb92fd7cb4d2ac0f362f431480770e9bbe7e1437d7c21b49a64e03e5f1cfb0eaf3f84f2435b972fdc1b00000000000000000000000000000000000000000000000000000000000000', 48 | expected: { 49 | contractName: 'WalletSimple', 50 | name: 'sendMultiSig', 51 | methodId: '0x39125215', 52 | args: [ 53 | { name: 'toAddress', 54 | type: 'address', 55 | value: '0xb19fb72b55f5374a062ddcba874e566b1d93f5d3' }, 56 | { name: 'value', type: 'uint256', value: '100000000000000000' }, 57 | { name: 'data', type: 'bytes', value: '0x' }, 58 | { name: 'expireTime', type: 'uint256', value: '1602018833' }, 59 | { name: 'sequenceId', type: 'uint256', value: '1' }, 60 | { name: 'signature', 61 | type: 'bytes', 62 | value: 63 | '0x6508bd6fc3da79ff7e5b84ff79f50e48112579d7b5190caeb92fd7cb4d2ac0f362f431480770e9bbe7e1437d7c21b49a64e03e5f1cfb0eaf3f84f2435b972fdc1b' }, 64 | ], 65 | }, 66 | }, 67 | ]; 68 | 69 | const failCases: string[] = [ 70 | '0x1234123412341234', 71 | '0x', 72 | '0x00', 73 | '0xabcd', 74 | ]; 75 | 76 | 77 | describe('Decoder', () => { 78 | const chainName = 'eth'; 79 | const ethFactory = getContractsFactory(chainName); 80 | let decoder: Decoder; 81 | 82 | before(() => { 83 | decoder = ethFactory.getDecoder(); 84 | }); 85 | 86 | it('Should be able to decode various function calls', function() { 87 | for (const { data, expected } of testCases) { 88 | expect(decoder.decode(Buffer.from(stripHexPrefix(data), 'hex'))).toEqual(expected); 89 | } 90 | }); 91 | 92 | it('Should be able to decode various function calls with a string hex data', function() { 93 | for (const { data, expected } of testCases) { 94 | expect(decoder.decode(data)).toEqual(expected); 95 | } 96 | }); 97 | 98 | it('Should fail to decode an unknown function call', function() { 99 | for (const data of failCases) { 100 | expect(() => decoder.decode(Buffer.from(stripHexPrefix(data), 'hex'))).toThrow('Unknown method'); 101 | } 102 | }); 103 | }); 104 | -------------------------------------------------------------------------------- /test/chain/trx/contract.test.ts: -------------------------------------------------------------------------------- 1 | const expect = require('expect'); // tslint:disable-line 2 | import * as fs from 'fs'; 3 | import { Contract } from '../../../src/base/contracts/contracts'; 4 | import { MethodDefinition } from '../../../src/base/methods/methods'; 5 | import { ContractInstance } from '../../../src/base/contracts/contractInstances'; 6 | import { TrxMethodDefinition } from '../../../src/trx/methods/methods'; 7 | import { getContractsFactory } from '../../../src'; 8 | import { getKnownSolidityTypes, getSolidityParameter, testFuzzedContractMethods } from '../../testutil'; 9 | 10 | 11 | describe('TRX Contracts', () => { 12 | const chainName = 'trx'; 13 | const trxContractFactory = getContractsFactory(chainName); 14 | 15 | const testStaticContracts = (callback: (contract: Contract, instanceName?: string) => void) => { 16 | trxContractFactory.listContractTypes().forEach((abiFileName) => { 17 | callback(trxContractFactory.getContract(abiFileName)); 18 | }); 19 | }; 20 | 21 | 22 | describe('Test Trx Contracts ABIs', () => { 23 | let instanceConfig: { [key: string]: ContractInstance }; 24 | 25 | before(() => { 26 | instanceConfig = JSON.parse(fs.readFileSync('trx/config/instances.json', 'utf-8')); 27 | }); 28 | 29 | testStaticContracts((contract: Contract) => { 30 | describe(`${contract.name}`, () => { 31 | const getRandomInstanceName = () => { 32 | const potentialInstances = instanceConfig[contract.name]; 33 | const instanceIndex = Math.floor(Math.random() * Object.keys(potentialInstances).length); 34 | return Object.keys(potentialInstances)[instanceIndex]; 35 | }; 36 | 37 | it('Should instantiate correctly', () => { 38 | expect(contract).toBeDefined(); 39 | }); 40 | 41 | it('Should fail to instantiate an unknown instance name', () => { 42 | const unknownInstanceName = 'fakeinstance'; 43 | expect(() => contract.instance(unknownInstanceName)).toThrow(`Unknown instance: ${unknownInstanceName}`); 44 | }); 45 | 46 | 47 | it('Should succeed when given parameters to a function that doesnt require them', () => { 48 | const methodsWithoutParameters = contract.listMethods() 49 | .filter((method: any) => method.inputs.length === 0); 50 | 51 | methodsWithoutParameters.forEach((method: MethodDefinition) => { 52 | getKnownSolidityTypes(chainName).forEach((type) => { 53 | const { data } = contract.instance().methods()[method.name].call({ unexpectedParam: getSolidityParameter(chainName, type) }); 54 | expect(data).toBeDefined(); 55 | }); 56 | }); 57 | }); 58 | 59 | it('Should fail when given no parameters to a function that requires them', () => { 60 | // Since methods can overload each other we have to double check that it actually has only no params 61 | const methodsWithoutParameters: Set = new Set(); 62 | const methodsWithParameters: MethodDefinition[] = contract.listMethods() 63 | .filter((method: MethodDefinition) => { 64 | // TODO(STLX-1617): Fix returned MethodDefinition type for each chain 65 | const castedMethod = method as TrxMethodDefinition; 66 | const noParams = castedMethod.inputs!.length === 0; 67 | if (noParams) { 68 | methodsWithoutParameters.add(castedMethod.name); 69 | } 70 | return !noParams; 71 | }) 72 | .filter((method: MethodDefinition) => !methodsWithoutParameters.has(method.name)); 73 | 74 | methodsWithParameters.forEach((method: MethodDefinition) => { 75 | expect(() => contract.instance().methods()[method.name].call({})).toThrow('Missing required parameter'); 76 | }); 77 | }); 78 | 79 | it('Should succeed when given expected parameters', () => { 80 | testFuzzedContractMethods(chainName, contract, ({ data }) => { 81 | expect(data).toBeDefined(); 82 | }); 83 | }); 84 | 85 | it('Should succeed with custom address instances', () => { 86 | const instanceAddress = getSolidityParameter(chainName, 'address'); 87 | testFuzzedContractMethods(chainName, contract, ({ data }) => { 88 | expect(data).toBeDefined(); 89 | }, { address: instanceAddress }); 90 | }); 91 | 92 | it('Should succeed with instances referenced by name', () => { 93 | const instanceName = getRandomInstanceName(); 94 | if (instanceName) { 95 | testFuzzedContractMethods(chainName, contract, ({ data }) => { 96 | expect(data).toBeDefined(); 97 | }, { instanceName }); 98 | } 99 | }); 100 | 101 | }); 102 | }); 103 | }); 104 | 105 | }); 106 | -------------------------------------------------------------------------------- /test/chain/trx/decoder.test.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src'; 2 | import { Decoder, FunctionCallExplanation } from '../../../src/base/decoder/decoder'; 3 | import { stripHexPrefix } from '../../../src/util/string'; 4 | const expect = require('expect'); 5 | 6 | interface TestCase { 7 | data: string; 8 | expected: FunctionCallExplanation; 9 | } 10 | 11 | const testCases: TestCase[] = [ 12 | { 13 | data: '0xa9059cbb000000000000000000000000493cb0a093df510e760120820c5964c225542a470000000000000000000000000000000000000000000000000000000005f5e100', 14 | expected: { methodId: '0xa9059cbb', 15 | name: 'transfer', 16 | args: 17 | [{ name: '_to', 18 | type: 'address', 19 | value: 'TGeT2sfMYcjx3ra2HhQUvMyBcVhjBc1Lbk' }, 20 | { name: '_value', type: 'uint256', value: '100000000' }], 21 | contractName: 'WrappedToken', 22 | }, 23 | }, 24 | { 25 | data: '2bf90baae56b297abc4ac59b0416123b2b0cc43f68e8932b84df04350fad7d27d6ff349a', 26 | expected: { methodId: '0x2bf90baa', 27 | name: 'confirmMintRequest', 28 | args: 29 | [{ name: 'requestHash', 30 | type: 'bytes32', 31 | value: 32 | '0xe56b297abc4ac59b0416123b2b0cc43f68e8932b84df04350fad7d27d6ff349a' }], 33 | contractName: 'WrappedTokenFactory' }, 34 | }, 35 | { 36 | data: '4e71e0c8', 37 | expected: { methodId: '0x4e71e0c8', 38 | name: 'claimOwnership', 39 | args: [], 40 | contractName: 'WrappedTokenMembers' }, 41 | }, 42 | { 43 | data: '8e24a7640000000000000000000000000000000000000000000000000000000252ad4ddc000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004032306138343534336231363262663663373230653766393937653534323963363836613534616665626664393239613433386138376565653737343732616566000000000000000000000000000000000000000000000000000000000000002233504153766f413976314a4c784875316b79567a336e3447566f6732334769364a79000000000000000000000000000000000000000000000000000000000000', 44 | expected: { methodId: '0x8e24a764', 45 | name: 'addMintRequest', 46 | args: 47 | [{ name: 'amount', type: 'uint256', value: '9977023964' }, 48 | { name: 'txid', 49 | type: 'string', 50 | value: 51 | '20a84543b162bf6c720e7f997e5429c686a54afebfd929a438a87eee77472aef' }, 52 | { name: 'depositAddress', 53 | type: 'string', 54 | value: '3PASvoA9v1JLxHu1kyVz3n4GVog23Gi6Jy' }], 55 | contractName: 'WrappedTokenFactory' }, 56 | }, 57 | ]; 58 | 59 | const failCases: string[] = [ 60 | '0x1234123412341234', 61 | '0x', 62 | '0x00', 63 | '0xabcd', 64 | ]; 65 | 66 | 67 | describe('Decoder', () => { 68 | const chainName = 'trx'; 69 | const ethFactory = getContractsFactory(chainName); 70 | let decoder: Decoder; 71 | 72 | before(() => { 73 | decoder = ethFactory.getDecoder(); 74 | }); 75 | 76 | it('Should be able to decode various function calls', function() { 77 | for (const { data, expected } of testCases) { 78 | expect(decoder.decode(Buffer.from(stripHexPrefix(data), 'hex'))).toEqual(expected); 79 | } 80 | }); 81 | 82 | it('Should fail to decode an unknown function call', function() { 83 | for (const data of failCases) { 84 | expect(() => decoder.decode(Buffer.from(stripHexPrefix(data), 'hex'))).toThrow('Unknown method'); 85 | } 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /test/testutil.ts: -------------------------------------------------------------------------------- 1 | import { ensure } from '../src/util/ensure'; 2 | import BigNumber from 'bignumber.js'; 3 | import { Contract } from '../src/base/contracts/contracts'; 4 | import { Parameter, MethodResponse } from '../src/base/methods/methods'; 5 | const tronweb = require('tronweb'); 6 | 7 | const generateNumber = (max: number) => { 8 | return (): string => { 9 | return BigNumber.random(18).times(max).integerValue(BigNumber.ROUND_FLOOR).toString(10); 10 | }; 11 | }; 12 | 13 | const generateSignedInteger = (max: number) => { 14 | return (): string => { 15 | const unsigned = generateNumber(max)(); 16 | const sign = generateNumber(2)(); 17 | return sign ? unsigned : (new BigNumber(unsigned).times(-1)).toString(10); 18 | }; 19 | }; 20 | 21 | const generateHexString = (length: number): () => string => { 22 | return () => { 23 | ensure(length % 2 === 0, `Invalid hex length: ${length}`); 24 | let result = '0x'; 25 | for (let i = 0; i < length / 2; i++) { 26 | const byte = new BigNumber(generateNumber(256)()); 27 | result += byte.toString(16); 28 | } 29 | return result; 30 | }; 31 | }; 32 | 33 | const generateHexStringArray = (strLength: number, arrLength: number): () => string[] => { 34 | return () => { 35 | const res: string[] = []; 36 | for (let i = 0; i < arrLength; i++) { 37 | res.push(generateHexString(strLength)()); 38 | } 39 | return res; 40 | }; 41 | }; 42 | 43 | const generateFromOptions = (options: any[]) => { 44 | return () => { 45 | return options[Number(generateNumber(options.length)())]; 46 | }; 47 | }; 48 | 49 | const generateTrxAddress = () => { 50 | return () => { 51 | return tronweb.utils.accounts.generateAccount().address.base58; 52 | }; 53 | }; 54 | 55 | const generateTrxHexString = (length: number): () => string => { 56 | return () => { 57 | ensure(length % 2 === 0, `Invalid hex length: ${length}`); 58 | let result = '0x'; 59 | for (let i = 0; i < length / 2; i++) { 60 | const byte = new BigNumber(generateNumber(256)()); 61 | result += tronweb.utils.bytes.byte2hexStr(byte.toNumber()); 62 | } 63 | return result; 64 | }; 65 | }; 66 | 67 | const generateEthAddress = () => { 68 | return () => { 69 | return '0x61E64B5224f88944222c4Aa7CCE1809c17106De5'; 70 | }; 71 | }; 72 | 73 | const generateIntArrray = (arr:string[]) => { 74 | return () => { 75 | return arr; 76 | }; 77 | }; 78 | 79 | const solidityTypes: { [key: string]: any } = { 80 | eth: { 81 | uint: generateNumber(2e8), 82 | uint8: generateNumber(2e2), 83 | uint16: generateNumber(2e4), 84 | uint32: generateNumber(2e8), 85 | uint64: generateNumber(2e8), 86 | uint128: generateNumber(2e8), 87 | uint256: generateNumber(2e16), 88 | int256: generateSignedInteger(2e8), 89 | bool: generateFromOptions([true, false]), 90 | address: generateEthAddress(), 91 | bytes: generateHexString(32), 92 | bytes1: generateHexString(2), 93 | bytes2: generateHexString(4), 94 | bytes3: generateHexString(6), 95 | bytes4: generateHexString(8), 96 | bytes8: generateHexString(16), 97 | bytes16: generateHexString(32), 98 | bytes32: generateHexString(64), 99 | string: generateFromOptions(['asdfadsf', 'hello world', 'test']), 100 | ['address[]']: generateHexStringArray(40, 1), 101 | ['uint8[]']: generateIntArrray([generateNumber(2e2)(), generateNumber(2e2)()]), 102 | ['uint256[]']: generateIntArrray([generateNumber(2e16)(), generateNumber(2e8)()]), 103 | ['bytes[]']: generateHexStringArray(40, 1), 104 | uint24: generateNumber(2e4), 105 | uint160: generateNumber(2e8), 106 | int24: generateNumber(2e4), 107 | }, 108 | trx: { 109 | uint: generateNumber(2e8), 110 | uint8: generateNumber(2e2), 111 | uint16: generateNumber(2e4), 112 | uint32: generateNumber(2e8), 113 | uint64: generateNumber(2e8), 114 | uint128: generateNumber(2e8), 115 | uint256: generateNumber(2e16), 116 | int256: generateSignedInteger(2e8), 117 | bool: generateFromOptions([true, false]), 118 | address: generateTrxAddress(), // generate valid tron address 119 | bytes32: generateTrxHexString(64), 120 | string: generateFromOptions(['asdfadsf', 'hello world', 'test']), 121 | }, 122 | }; 123 | 124 | export function getKnownSolidityTypes(chainName: string): string[] { 125 | return Object.keys(solidityTypes[chainName]); 126 | } 127 | 128 | export function getSolidityParameter(chainName: string, type: string): any { 129 | ensure(solidityTypes[chainName][type], `Unknown type: ${type}`); 130 | return solidityTypes[chainName][type](); 131 | } 132 | 133 | export function testFuzzedContractMethods (chainName:string, contract: Contract, callback: (response: MethodResponse) => void, args?: any) { 134 | const allMethods = contract.listMethods(); 135 | const FUZZING_REPETITIONS = 5; 136 | allMethods.forEach((methodDefinition: any) => { 137 | const params = methodDefinition.inputs; 138 | const name = methodDefinition.name; 139 | 140 | for (let i = 0; i < FUZZING_REPETITIONS; i++) { 141 | let args: { [key: string]: any } = {}; 142 | params.forEach((param: Parameter) => { 143 | if (param.type === 'tuple') { 144 | const obj :{[key: string]: any} = {}; 145 | param.components.forEach((key:{name: string, type: string}) => { 146 | obj[key.name] = getSolidityParameter(chainName, key.type); 147 | }); 148 | args = obj; 149 | } else { 150 | args[param.name] = getSolidityParameter(chainName, param.type); 151 | } 152 | 153 | }); 154 | const contractInstance = contract.instance(args.instanceName || 'default'); 155 | 156 | if (args.address) { 157 | contractInstance.address = args.address; 158 | } 159 | 160 | callback(contractInstance.methods()[name].call(args)); 161 | } 162 | }); 163 | } 164 | 165 | -------------------------------------------------------------------------------- /trx/abis/WrappedToken.json: -------------------------------------------------------------------------------- 1 | { 2 | "entrys": [ 3 | { 4 | "outputs": [{ "type": "bool" }], 5 | "constant": true, 6 | "name": "mintingFinished", 7 | "stateMutability": "View", 8 | "type": "Function" 9 | }, 10 | { 11 | "outputs": [{ "type": "string" }], 12 | "constant": true, 13 | "name": "name", 14 | "stateMutability": "View", 15 | "type": "Function" 16 | }, 17 | { 18 | "outputs": [{ "type": "bool" }], 19 | "inputs": [ 20 | { "name": "_spender", "type": "address" }, 21 | { "name": "_value", "type": "uint256" } 22 | ], 23 | "name": "approve", 24 | "stateMutability": "Nonpayable", 25 | "type": "Function" 26 | }, 27 | { 28 | "inputs": [{ "name": "_token", "type": "address" }], 29 | "name": "reclaimToken", 30 | "stateMutability": "Nonpayable", 31 | "type": "Function" 32 | }, 33 | { 34 | "outputs": [{ "type": "uint256" }], 35 | "constant": true, 36 | "name": "totalSupply", 37 | "stateMutability": "View", 38 | "type": "Function" 39 | }, 40 | { 41 | "outputs": [{ "type": "bool" }], 42 | "inputs": [ 43 | { "name": "_from", "type": "address" }, 44 | { "name": "_to", "type": "address" }, 45 | { "name": "_value", "type": "uint256" } 46 | ], 47 | "name": "transferFrom", 48 | "stateMutability": "Nonpayable", 49 | "type": "Function" 50 | }, 51 | { 52 | "outputs": [{ "type": "uint8" }], 53 | "constant": true, 54 | "name": "decimals", 55 | "stateMutability": "View", 56 | "type": "Function" 57 | }, 58 | { "name": "unpause", "stateMutability": "Nonpayable", "type": "Function" }, 59 | { 60 | "outputs": [{ "type": "bool" }], 61 | "inputs": [ 62 | { "name": "_to", "type": "address" }, 63 | { "name": "_amount", "type": "uint256" } 64 | ], 65 | "name": "mint", 66 | "stateMutability": "Nonpayable", 67 | "type": "Function" 68 | }, 69 | { 70 | "inputs": [{ "name": "value", "type": "uint256" }], 71 | "name": "burn", 72 | "stateMutability": "Nonpayable", 73 | "type": "Function" 74 | }, 75 | { 76 | "name": "claimOwnership", 77 | "stateMutability": "Nonpayable", 78 | "type": "Function" 79 | }, 80 | { 81 | "outputs": [{ "type": "bool" }], 82 | "constant": true, 83 | "name": "paused", 84 | "stateMutability": "View", 85 | "type": "Function" 86 | }, 87 | { 88 | "outputs": [{ "name": "success", "type": "bool" }], 89 | "inputs": [ 90 | { "name": "_spender", "type": "address" }, 91 | { "name": "_subtractedValue", "type": "uint256" } 92 | ], 93 | "name": "decreaseApproval", 94 | "stateMutability": "Nonpayable", 95 | "type": "Function" 96 | }, 97 | { 98 | "outputs": [{ "type": "uint256" }], 99 | "constant": true, 100 | "inputs": [{ "name": "_owner", "type": "address" }], 101 | "name": "balanceOf", 102 | "stateMutability": "View", 103 | "type": "Function" 104 | }, 105 | { 106 | "name": "renounceOwnership", 107 | "stateMutability": "Nonpayable", 108 | "type": "Function" 109 | }, 110 | { 111 | "outputs": [{ "type": "bool" }], 112 | "name": "finishMinting", 113 | "stateMutability": "Nonpayable", 114 | "type": "Function" 115 | }, 116 | { "name": "pause", "stateMutability": "Nonpayable", "type": "Function" }, 117 | { 118 | "outputs": [{ "type": "address" }], 119 | "constant": true, 120 | "name": "owner", 121 | "stateMutability": "View", 122 | "type": "Function" 123 | }, 124 | { 125 | "outputs": [{ "type": "string" }], 126 | "constant": true, 127 | "name": "symbol", 128 | "stateMutability": "View", 129 | "type": "Function" 130 | }, 131 | { 132 | "outputs": [{ "type": "bool" }], 133 | "inputs": [ 134 | { "name": "_to", "type": "address" }, 135 | { "name": "_value", "type": "uint256" } 136 | ], 137 | "name": "transfer", 138 | "stateMutability": "Nonpayable", 139 | "type": "Function" 140 | }, 141 | { 142 | "outputs": [{ "name": "success", "type": "bool" }], 143 | "inputs": [ 144 | { "name": "_spender", "type": "address" }, 145 | { "name": "_addedValue", "type": "uint256" } 146 | ], 147 | "name": "increaseApproval", 148 | "stateMutability": "Nonpayable", 149 | "type": "Function" 150 | }, 151 | { 152 | "outputs": [{ "type": "uint256" }], 153 | "constant": true, 154 | "inputs": [ 155 | { "name": "_owner", "type": "address" }, 156 | { "name": "_spender", "type": "address" } 157 | ], 158 | "name": "allowance", 159 | "stateMutability": "View", 160 | "type": "Function" 161 | }, 162 | { 163 | "outputs": [{ "type": "address" }], 164 | "constant": true, 165 | "name": "pendingOwner", 166 | "stateMutability": "View", 167 | "type": "Function" 168 | }, 169 | { 170 | "inputs": [{ "name": "newOwner", "type": "address" }], 171 | "name": "transferOwnership", 172 | "stateMutability": "Nonpayable", 173 | "type": "Function" 174 | }, 175 | { "name": "Pause", "type": "Event" }, 176 | { "name": "Unpause", "type": "Event" }, 177 | { 178 | "inputs": [ 179 | { "indexed": true, "name": "burner", "type": "address" }, 180 | { "name": "value", "type": "uint256" } 181 | ], 182 | "name": "Burn", 183 | "type": "Event" 184 | }, 185 | { 186 | "inputs": [ 187 | { "indexed": true, "name": "to", "type": "address" }, 188 | { "name": "amount", "type": "uint256" } 189 | ], 190 | "name": "Mint", 191 | "type": "Event" 192 | }, 193 | { "name": "MintFinished", "type": "Event" }, 194 | { 195 | "inputs": [ 196 | { "indexed": true, "name": "previousOwner", "type": "address" } 197 | ], 198 | "name": "OwnershipRenounced", 199 | "type": "Event" 200 | }, 201 | { 202 | "inputs": [ 203 | { "indexed": true, "name": "previousOwner", "type": "address" }, 204 | { "indexed": true, "name": "newOwner", "type": "address" } 205 | ], 206 | "name": "OwnershipTransferred", 207 | "type": "Event" 208 | }, 209 | { 210 | "inputs": [ 211 | { "indexed": true, "name": "owner", "type": "address" }, 212 | { "indexed": true, "name": "spender", "type": "address" }, 213 | { "name": "value", "type": "uint256" } 214 | ], 215 | "name": "Approval", 216 | "type": "Event" 217 | }, 218 | { 219 | "inputs": [ 220 | { "indexed": true, "name": "from", "type": "address" }, 221 | { "indexed": true, "name": "to", "type": "address" }, 222 | { "name": "value", "type": "uint256" } 223 | ], 224 | "name": "Transfer", 225 | "type": "Event" 226 | } 227 | ] 228 | } 229 | -------------------------------------------------------------------------------- /trx/abis/WrappedTokenController.json: -------------------------------------------------------------------------------- 1 | { 2 | "entrys": [ 3 | { 4 | "inputs": [{ "name": "_token", "type": "address" }], 5 | "name": "reclaimToken", 6 | "stateMutability": "Nonpayable", 7 | "type": "Function" 8 | }, 9 | { 10 | "outputs": [{ "type": "bool" }], 11 | "constant": true, 12 | "inputs": [{ "name": "addr", "type": "address" }], 13 | "name": "isMerchant", 14 | "stateMutability": "View", 15 | "type": "Function" 16 | }, 17 | { 18 | "outputs": [{ "type": "address" }], 19 | "constant": true, 20 | "name": "getToken", 21 | "stateMutability": "View", 22 | "type": "Function" 23 | }, 24 | { 25 | "outputs": [{ "type": "bool" }], 26 | "inputs": [{ "name": "contractToOwn", "type": "address" }], 27 | "name": "callClaimOwnership", 28 | "stateMutability": "Nonpayable", 29 | "type": "Function" 30 | }, 31 | { 32 | "outputs": [{ "type": "bool" }], 33 | "constant": true, 34 | "inputs": [{ "name": "addr", "type": "address" }], 35 | "name": "isCustodian", 36 | "stateMutability": "View", 37 | "type": "Function" 38 | }, 39 | { 40 | "outputs": [{ "type": "bool" }], 41 | "name": "unpause", 42 | "stateMutability": "Nonpayable", 43 | "type": "Function" 44 | }, 45 | { 46 | "outputs": [{ "type": "bool" }], 47 | "inputs": [ 48 | { "name": "to", "type": "address" }, 49 | { "name": "amount", "type": "uint256" } 50 | ], 51 | "name": "mint", 52 | "stateMutability": "Nonpayable", 53 | "type": "Function" 54 | }, 55 | { 56 | "outputs": [{ "type": "bool" }], 57 | "inputs": [{ "name": "value", "type": "uint256" }], 58 | "name": "burn", 59 | "stateMutability": "Nonpayable", 60 | "type": "Function" 61 | }, 62 | { 63 | "outputs": [{ "type": "bool" }], 64 | "inputs": [ 65 | { "name": "ownedContract", "type": "address" }, 66 | { "name": "_token", "type": "address" } 67 | ], 68 | "name": "callReclaimToken", 69 | "stateMutability": "Nonpayable", 70 | "type": "Function" 71 | }, 72 | { 73 | "name": "claimOwnership", 74 | "stateMutability": "Nonpayable", 75 | "type": "Function" 76 | }, 77 | { 78 | "outputs": [{ "type": "bool" }], 79 | "inputs": [{ "name": "_factory", "type": "address" }], 80 | "name": "setFactory", 81 | "stateMutability": "Nonpayable", 82 | "type": "Function" 83 | }, 84 | { 85 | "name": "renounceOwnership", 86 | "stateMutability": "Nonpayable", 87 | "type": "Function" 88 | }, 89 | { 90 | "outputs": [{ "type": "bool" }], 91 | "name": "pause", 92 | "stateMutability": "Nonpayable", 93 | "type": "Function" 94 | }, 95 | { 96 | "outputs": [{ "type": "address" }], 97 | "constant": true, 98 | "name": "owner", 99 | "stateMutability": "View", 100 | "type": "Function" 101 | }, 102 | { 103 | "outputs": [{ "type": "address" }], 104 | "constant": true, 105 | "name": "members", 106 | "stateMutability": "View", 107 | "type": "Function" 108 | }, 109 | { 110 | "outputs": [{ "type": "address" }], 111 | "constant": true, 112 | "name": "factory", 113 | "stateMutability": "View", 114 | "type": "Function" 115 | }, 116 | { 117 | "outputs": [{ "type": "address" }], 118 | "constant": true, 119 | "name": "pendingOwner", 120 | "stateMutability": "View", 121 | "type": "Function" 122 | }, 123 | { 124 | "outputs": [{ "type": "bool" }], 125 | "inputs": [ 126 | { "name": "ownedContract", "type": "address" }, 127 | { "name": "newOwner", "type": "address" } 128 | ], 129 | "name": "callTransferOwnership", 130 | "stateMutability": "Nonpayable", 131 | "type": "Function" 132 | }, 133 | { 134 | "inputs": [{ "name": "newOwner", "type": "address" }], 135 | "name": "transferOwnership", 136 | "stateMutability": "Nonpayable", 137 | "type": "Function" 138 | }, 139 | { 140 | "outputs": [{ "type": "bool" }], 141 | "inputs": [{ "name": "_members", "type": "address" }], 142 | "name": "setMembers", 143 | "stateMutability": "Nonpayable", 144 | "type": "Function" 145 | }, 146 | { 147 | "outputs": [{ "type": "address" }], 148 | "constant": true, 149 | "name": "token", 150 | "stateMutability": "View", 151 | "type": "Function" 152 | }, 153 | { 154 | "inputs": [{ "name": "_token", "type": "address" }], 155 | "stateMutability": "Nonpayable", 156 | "type": "Constructor" 157 | }, 158 | { 159 | "inputs": [{ "indexed": true, "name": "members", "type": "address" }], 160 | "name": "MembersSet", 161 | "type": "Event" 162 | }, 163 | { 164 | "inputs": [{ "indexed": true, "name": "factory", "type": "address" }], 165 | "name": "FactorySet", 166 | "type": "Event" 167 | }, 168 | { "name": "Paused", "type": "Event" }, 169 | { "name": "Unpaused", "type": "Event" }, 170 | { 171 | "inputs": [ 172 | { "name": "ownedContract", "type": "address" }, 173 | { "name": "newOwner", "type": "address" } 174 | ], 175 | "name": "CalledTransferOwnership", 176 | "type": "Event" 177 | }, 178 | { 179 | "inputs": [{ "name": "contractToOwn", "type": "address" }], 180 | "name": "CalledClaimOwnership", 181 | "type": "Event" 182 | }, 183 | { 184 | "inputs": [ 185 | { "name": "ownedContract", "type": "address" }, 186 | { "name": "_token", "type": "address" } 187 | ], 188 | "name": "CalledReclaimToken", 189 | "type": "Event" 190 | }, 191 | { 192 | "inputs": [ 193 | { "indexed": true, "name": "previousOwner", "type": "address" } 194 | ], 195 | "name": "OwnershipRenounced", 196 | "type": "Event" 197 | }, 198 | { 199 | "inputs": [ 200 | { "indexed": true, "name": "previousOwner", "type": "address" }, 201 | { "indexed": true, "name": "newOwner", "type": "address" } 202 | ], 203 | "name": "OwnershipTransferred", 204 | "type": "Event" 205 | } 206 | ] 207 | } 208 | -------------------------------------------------------------------------------- /trx/abis/WrappedTokenMembers.json: -------------------------------------------------------------------------------- 1 | { 2 | "entrys": [ 3 | { 4 | "outputs": [{ "type": "bool" }], 5 | "inputs": [{ "name": "merchant", "type": "address" }], 6 | "name": "removeMerchant", 7 | "stateMutability": "Nonpayable", 8 | "type": "Function" 9 | }, 10 | { 11 | "inputs": [{ "name": "_token", "type": "address" }], 12 | "name": "reclaimToken", 13 | "stateMutability": "Nonpayable", 14 | "type": "Function" 15 | }, 16 | { 17 | "outputs": [{ "type": "bool" }], 18 | "constant": true, 19 | "inputs": [{ "name": "addr", "type": "address" }], 20 | "name": "isMerchant", 21 | "stateMutability": "View", 22 | "type": "Function" 23 | }, 24 | { 25 | "outputs": [{ "type": "bool" }], 26 | "constant": true, 27 | "inputs": [{ "name": "addr", "type": "address" }], 28 | "name": "isCustodian", 29 | "stateMutability": "View", 30 | "type": "Function" 31 | }, 32 | { 33 | "outputs": [{ "type": "address" }], 34 | "constant": true, 35 | "name": "custodian", 36 | "stateMutability": "View", 37 | "type": "Function" 38 | }, 39 | { 40 | "outputs": [{ "type": "bool" }], 41 | "inputs": [{ "name": "_custodian", "type": "address" }], 42 | "name": "setCustodian", 43 | "stateMutability": "Nonpayable", 44 | "type": "Function" 45 | }, 46 | { 47 | "name": "claimOwnership", 48 | "stateMutability": "Nonpayable", 49 | "type": "Function" 50 | }, 51 | { 52 | "outputs": [{ "type": "address" }], 53 | "constant": true, 54 | "inputs": [{ "name": "index", "type": "uint256" }], 55 | "name": "getMerchant", 56 | "stateMutability": "View", 57 | "type": "Function" 58 | }, 59 | { 60 | "name": "renounceOwnership", 61 | "stateMutability": "Nonpayable", 62 | "type": "Function" 63 | }, 64 | { 65 | "outputs": [{ "type": "address" }], 66 | "constant": true, 67 | "name": "owner", 68 | "stateMutability": "View", 69 | "type": "Function" 70 | }, 71 | { 72 | "outputs": [{ "type": "bool" }], 73 | "inputs": [{ "name": "merchant", "type": "address" }], 74 | "name": "addMerchant", 75 | "stateMutability": "Nonpayable", 76 | "type": "Function" 77 | }, 78 | { 79 | "outputs": [{ "type": "address[]" }], 80 | "constant": true, 81 | "name": "getMerchants", 82 | "stateMutability": "View", 83 | "type": "Function" 84 | }, 85 | { 86 | "outputs": [{ "type": "address" }], 87 | "constant": true, 88 | "name": "pendingOwner", 89 | "stateMutability": "View", 90 | "type": "Function" 91 | }, 92 | { 93 | "inputs": [{ "name": "newOwner", "type": "address" }], 94 | "name": "transferOwnership", 95 | "stateMutability": "Nonpayable", 96 | "type": "Function" 97 | }, 98 | { 99 | "inputs": [{ "name": "_owner", "type": "address" }], 100 | "stateMutability": "Nonpayable", 101 | "type": "Constructor" 102 | }, 103 | { 104 | "inputs": [{ "indexed": true, "name": "custodian", "type": "address" }], 105 | "name": "CustodianSet", 106 | "type": "Event" 107 | }, 108 | { 109 | "inputs": [{ "indexed": true, "name": "merchant", "type": "address" }], 110 | "name": "MerchantAdd", 111 | "type": "Event" 112 | }, 113 | { 114 | "inputs": [{ "indexed": true, "name": "merchant", "type": "address" }], 115 | "name": "MerchantRemove", 116 | "type": "Event" 117 | }, 118 | { 119 | "inputs": [ 120 | { "indexed": true, "name": "previousOwner", "type": "address" } 121 | ], 122 | "name": "OwnershipRenounced", 123 | "type": "Event" 124 | }, 125 | { 126 | "inputs": [ 127 | { "indexed": true, "name": "previousOwner", "type": "address" }, 128 | { "indexed": true, "name": "newOwner", "type": "address" } 129 | ], 130 | "name": "OwnershipTransferred", 131 | "type": "Event" 132 | } 133 | ] 134 | } 135 | -------------------------------------------------------------------------------- /trx/abis/index.ts: -------------------------------------------------------------------------------- 1 | import WrappedToken from './WrappedToken.json'; 2 | import WrappedTokenFactory from './WrappedTokenFactory.json'; 3 | import WrappedTokenController from './WrappedTokenController.json'; 4 | import WrappedTokenMembers from './WrappedTokenMembers.json'; 5 | 6 | export default { 7 | WrappedToken, 8 | WrappedTokenFactory, 9 | WrappedTokenController, 10 | WrappedTokenMembers, 11 | }; 12 | -------------------------------------------------------------------------------- /trx/config/instances.json: -------------------------------------------------------------------------------- 1 | { 2 | "WrappedToken": { 3 | "WBTC": "TXpw8XeWYeTUd4quDskoUqeQPowRh4jY65", 4 | "WETH": "TXWkP3jLBqRGojUih1ShzNyDaN5Csnebok" 5 | }, 6 | "WrappedTokenFactory":{ 7 | "WBTC": "TBm9acNsw9WSqZyf5gRD42kzLrZ7TwMpZd", 8 | "WETH": "TKCzLPPxsZdEGT7DfY6yNSiQntosswuBvy" 9 | }, 10 | "WrappedTokenController":{ 11 | "WBTC": "TUS7kU3eBz8jbDMamrVaU1suuYbt3mVnx3", 12 | "WETH": "TAtZzUrFfBPcTXMkV1RrtBzaw9YbeNuErj" 13 | }, 14 | "WrappedTokenMembers":{ 15 | "WBTC": "TEBKzUc6a2tCLuQQR3qaa29juQ3xh3GBYL", 16 | "WETH": "TFQv9DPAgdBcsRGaWTi4fn1GjJjPruNVMg" 17 | } 18 | } -------------------------------------------------------------------------------- /trx/examples/WrappedToken/pause.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | /** This example should provide just a methoid */ 3 | 4 | const tokenName = 'WBTC'; 5 | 6 | const contract = getContractsFactory('trx').getContract('WrappedToken').instance(tokenName); 7 | 8 | const result = contract.methods().pause.call({}); 9 | console.log(result.data); 10 | 11 | const decoder = getContractsFactory('trx').getDecoder(); 12 | 13 | const wbtcData = result.data.slice(2); 14 | const decoded = decoder.decode(Buffer.from(wbtcData, 'hex')); 15 | console.log(`\nTransfer decoded : cbce51775299bc0b2c87bd0724d6c1e72f7d2d3f0f82c68c1ec0155772a5c9b4 \n`, decoded); 16 | 17 | -------------------------------------------------------------------------------- /trx/examples/WrappedToken/transfer.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | 3 | const tokenName = 'WBTC'; 4 | const recipient = 'TGeT2sfMYcjx3ra2HhQUvMyBcVhjBc1Lbk'; 5 | const tokenAmount = 1e8; // 1 WBTC on Tron 6 | 7 | const contract = getContractsFactory('trx').getContract('WrappedToken').instance(tokenName); 8 | 9 | const wbtcContract = contract.methods().transfer.call({ _to: recipient, _value: tokenAmount.toString(10) }); 10 | 11 | const { data, amount } = wbtcContract; 12 | console.log(`To transfer ${tokenAmount} ${tokenName} to ${recipient}:\n`); 13 | console.log(`Data: ${data}`); 14 | console.log(`Amount: ${amount}`); 15 | console.log(`To: ${contract.address}`); 16 | 17 | 18 | const decoder = getContractsFactory('trx').getDecoder(); 19 | 20 | const wbtcData = data.slice(2); 21 | const decoded = decoder.decode(Buffer.from(wbtcData, 'hex')); 22 | console.log(`\nTransfer decoded : cbce51775299bc0b2c87bd0724d6c1e72f7d2d3f0f82c68c1ec0155772a5c9b4 \n`, decoded); 23 | 24 | 25 | const randomDecoded = decoder.decode(Buffer.from('a9059cbb000000000000000000000000efc230e125c24de35f6290afcafa28d50b43653600000000000000000000000000000000000000000000000000000000000003e8', 'hex')); 26 | console.log(`\nDecoded random transfer from tronscan, hash ref : cbce51775299bc0b2c87bd0724d6c1e72f7d2d3f0f82c68c1ec0155772a5c9b4 \n`, randomDecoded); 27 | -------------------------------------------------------------------------------- /trx/examples/WrappedTokenFactory/mintRequest.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../../src/index'; 2 | /** This example should provide just a methoid */ 3 | 4 | const tokenName = 'WBTC'; 5 | 6 | const contract = getContractsFactory('trx').getContract('WrappedTokenFactory').instance(tokenName); 7 | 8 | const custodianDepositAddress = '0xEeD5D8E8FaB6f5cBd6e1b14FC75FE4f14ee503dB'; 9 | const txId = 'f3b566050a4b57ca2acd1acdf9221a911d3740d9e7f9e0f3ddb468988f454ea1'; 10 | const amount = '18'; 11 | 12 | const response = contract.methods().addMintRequest.call({ amount: amount, txid: txId, depositAddress: custodianDepositAddress }); 13 | 14 | console.log('encoded', response); 15 | 16 | 17 | const decoder = getContractsFactory('trx').getDecoder(); 18 | 19 | const data = response.data; 20 | console.log(10, data ); 21 | /** Decode with string data */ 22 | const decodedFromString = decoder.decode(data); 23 | console.log(`\n AddMintRequest decoded from string: \n`, decodedFromString); 24 | /** Decode with Buffer data*/ 25 | const decodedFromBuffer = decoder.decode(Buffer.from(data.slice(2), 'hex')); 26 | console.log(`\n AddMintRequest decoded from Buffer: \n`, decodedFromBuffer); 27 | -------------------------------------------------------------------------------- /trx/examples/getContractList.ts: -------------------------------------------------------------------------------- 1 | import { getContractsFactory } from '../../src/index'; 2 | /** This example should provide just list of methods */ 3 | 4 | console.log(getContractsFactory('trx').getContract('WrappedToken').listMethods()); 5 | console.log(JSON.stringify(getContractsFactory('trx').getContract('WrappedTokenFactory').instance().methods(), null, 2)); 6 | console.log(getContractsFactory('trx').getContract('WrappedTokenController').listMethods()); 7 | console.log(getContractsFactory('trx').getContract('WrappedTokenMembers').listMethods()); 8 | 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "esModuleInterop": true, 5 | "target": "es6", 6 | "lib": [ 7 | "dom", 8 | "es6", 9 | "es5", 10 | "es2017" 11 | ], 12 | "noImplicitAny": false, 13 | "strictNullChecks": true, 14 | "moduleResolution": "node", 15 | "sourceMap": true, 16 | "outDir": "dist", 17 | "resolveJsonModule": true, 18 | "baseUrl": "./", 19 | "paths": { 20 | "*": [ 21 | "node_modules/*", 22 | "src/types/*" 23 | ] 24 | }, 25 | "skipLibCheck": true, 26 | "declaration": true, 27 | "declarationDir": "./dist/types" 28 | }, 29 | "include": [ 30 | "src/**/*" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | entry: './src/index.ts', 6 | mode: 'production', 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.ts?$/, 11 | use: 'ts-loader', 12 | exclude: /node_modules/, 13 | }, 14 | ], 15 | }, 16 | target: 'web', 17 | resolve: { 18 | extensions: ['.ts', '.js'], 19 | fallback: { 20 | stream: require.resolve('stream-browserify'), 21 | querystring: false, 22 | }, 23 | }, 24 | plugins: [ 25 | new webpack.ProvidePlugin({ 26 | process: 'process/browser', 27 | }), 28 | new webpack.ProvidePlugin({ 29 | Buffer: ['buffer', 'Buffer'], 30 | }), 31 | ], 32 | output: { 33 | path: path.resolve(__dirname, 'dist'), 34 | filename: 'lib.js', 35 | libraryTarget: 'umd', 36 | }, 37 | }; 38 | --------------------------------------------------------------------------------