bridge_ui: solana balances, begin wasm integration
Change-Id: Ifde4ec688ff678f46c1606e519fc36c0ece68fd4
This commit is contained in:
parent
591e68b5ee
commit
b1a237db99
|
@ -0,0 +1,28 @@
|
|||
const { addBeforeLoader, loaderByName } = require("@craco/craco");
|
||||
|
||||
module.exports = {
|
||||
webpack: {
|
||||
configure: (webpackConfig) => {
|
||||
const wasmExtensionRegExp = /\.wasm$/;
|
||||
webpackConfig.resolve.extensions.push(".wasm");
|
||||
|
||||
webpackConfig.module.rules.forEach((rule) => {
|
||||
(rule.oneOf || []).forEach((oneOf) => {
|
||||
if (oneOf.loader && oneOf.loader.indexOf("file-loader") >= 0) {
|
||||
oneOf.exclude.push(wasmExtensionRegExp);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const wasmLoader = {
|
||||
test: /\.wasm$/,
|
||||
include: /node_modules\/(bridge|token-bridge)/,
|
||||
loaders: ["wasm-loader"],
|
||||
};
|
||||
|
||||
addBeforeLoader(webpackConfig, loaderByName("file-loader"), wasmLoader);
|
||||
|
||||
return webpackConfig;
|
||||
},
|
||||
},
|
||||
};
|
|
@ -5,7 +5,9 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "test_ui",
|
||||
"version": "0.1.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@metamask/detect-provider": "^1.2.0",
|
||||
|
@ -13,16 +15,20 @@
|
|||
"@solana/wallet-base": "^0.0.1",
|
||||
"@solana/web3.js": "^1.22.0",
|
||||
"@typechain/ethers-v5": "^7.0.1",
|
||||
"bridge": "file:rust_modules\\core",
|
||||
"ethers": "^5.4.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3"
|
||||
"react-scripts": "4.0.3",
|
||||
"token-bridge": "file:rust_modules\\token"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@craco/craco": "^6.2.0",
|
||||
"@openzeppelin/contracts": "^4.2.0",
|
||||
"@truffle/hdwallet-provider": "^1.4.1",
|
||||
"copy-dir": "^1.3.0",
|
||||
"truffle": "^5.4.1"
|
||||
"truffle": "^5.4.1",
|
||||
"wasm-loader": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@apollo/client": {
|
||||
|
@ -2005,6 +2011,27 @@
|
|||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@craco/craco": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.2.0.tgz",
|
||||
"integrity": "sha512-kLc4GSdgR9D5JiZmSxtzbvBKcUFSJqMXImRjjYf5pacwiyAs3XfQwai7T+pExfLQNUnytgkL8jRFUJeYrkVr7g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"semver": "^7.3.2",
|
||||
"webpack-merge": "^4.2.2"
|
||||
},
|
||||
"bin": {
|
||||
"craco": "bin/craco.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-scripts": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@csstools/convert-colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
|
||||
|
@ -10222,6 +10249,10 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bridge": {
|
||||
"resolved": "rust_modules/core",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/brorand": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
|
||||
|
@ -34482,6 +34513,10 @@
|
|||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/token-bridge": {
|
||||
"resolved": "rust_modules/token",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
|
@ -35551,6 +35586,72 @@
|
|||
"makeerror": "1.0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/wasm-dce": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wasm-dce/-/wasm-dce-1.0.2.tgz",
|
||||
"integrity": "sha512-Fq1+nu43ybsjSnBquLrW/cULmKs61qbv9k8ep13QUe0nABBezMoNAA+j6QY66MW0/eoDVDp1rjXDqQ2VKyS/Xg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.0.0-beta.39",
|
||||
"@babel/traverse": "^7.0.0-beta.39",
|
||||
"@babel/types": "^7.0.0-beta.39",
|
||||
"babylon": "^7.0.0-beta.39",
|
||||
"webassembly-interpreter": "0.0.30"
|
||||
}
|
||||
},
|
||||
"node_modules/wasm-dce/node_modules/babylon": {
|
||||
"version": "7.0.0-beta.47",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz",
|
||||
"integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"babylon": "bin/babylon.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wasm-loader": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/wasm-loader/-/wasm-loader-1.3.0.tgz",
|
||||
"integrity": "sha512-R4s75XH+o8qM+WaRrAU9S2rbAMDzob18/S3V8R9ZoFpZkPWLAohWWlzWAp1ybeTkOuuku/X1zJtxiV0pBYxZww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loader-utils": "^1.1.0",
|
||||
"wasm-dce": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wasm-dce": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/wasm-loader/node_modules/json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/wasm-loader/node_modules/loader-utils": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
||||
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||
|
@ -36335,6 +36436,46 @@
|
|||
"xhr-request-promise": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/webassembly-floating-point-hex-parser": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/webassembly-floating-point-hex-parser/-/webassembly-floating-point-hex-parser-0.1.2.tgz",
|
||||
"integrity": "sha512-TUf1H++8U10+stJbFydnvrpG5Sznz5Rilez/oZlV5zI0C/e4cSxd8rALAJ8VpTvjVWxLmL3SVSJUK6Ap9AoiNg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/webassembly-interpreter": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/webassembly-interpreter/-/webassembly-interpreter-0.0.30.tgz",
|
||||
"integrity": "sha512-+Jdy2piEvz9T5j751mOE8+rBO12p+nNW6Fg4kJZ+zP1oUfsm+151sbAbM8AFxWTURmWCGP+r8Lxwfv3pzN1bCQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0-beta.36",
|
||||
"long": "^3.2.0",
|
||||
"webassembly-floating-point-hex-parser": "0.1.2"
|
||||
},
|
||||
"bin": {
|
||||
"wasm": "lib/bin/repl.js",
|
||||
"wasm2wast": "lib/bin/wasm2wast.js",
|
||||
"wasmast": "lib/bin/wasmast.js",
|
||||
"wasmdump": "lib/bin/wasmdump.js",
|
||||
"wasmrun": "lib/bin/wasmrun.js",
|
||||
"wastast": "lib/bin/wastast.js"
|
||||
}
|
||||
},
|
||||
"node_modules/webassembly-interpreter/node_modules/long": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
|
||||
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
|
||||
|
@ -37076,6 +37217,15 @@
|
|||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-merge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz",
|
||||
"integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-sources": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
|
||||
|
@ -38362,6 +38512,14 @@
|
|||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"rust_modules/core": {
|
||||
"name": "bridge",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"rust_modules/token": {
|
||||
"name": "token-bridge",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -39743,6 +39901,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@craco/craco": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.2.0.tgz",
|
||||
"integrity": "sha512-kLc4GSdgR9D5JiZmSxtzbvBKcUFSJqMXImRjjYf5pacwiyAs3XfQwai7T+pExfLQNUnytgkL8jRFUJeYrkVr7g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"semver": "^7.3.2",
|
||||
"webpack-merge": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"@csstools/convert-colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
|
||||
|
@ -46437,6 +46607,9 @@
|
|||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"bridge": {
|
||||
"version": "file:rust_modules/core"
|
||||
},
|
||||
"brorand": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
|
||||
|
@ -66128,6 +66301,9 @@
|
|||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"token-bridge": {
|
||||
"version": "file:rust_modules/token"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
|
@ -66999,6 +67175,60 @@
|
|||
"makeerror": "1.0.x"
|
||||
}
|
||||
},
|
||||
"wasm-dce": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wasm-dce/-/wasm-dce-1.0.2.tgz",
|
||||
"integrity": "sha512-Fq1+nu43ybsjSnBquLrW/cULmKs61qbv9k8ep13QUe0nABBezMoNAA+j6QY66MW0/eoDVDp1rjXDqQ2VKyS/Xg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/core": "^7.0.0-beta.39",
|
||||
"@babel/traverse": "^7.0.0-beta.39",
|
||||
"@babel/types": "^7.0.0-beta.39",
|
||||
"babylon": "^7.0.0-beta.39",
|
||||
"webassembly-interpreter": "0.0.30"
|
||||
},
|
||||
"dependencies": {
|
||||
"babylon": {
|
||||
"version": "7.0.0-beta.47",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz",
|
||||
"integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"wasm-loader": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/wasm-loader/-/wasm-loader-1.3.0.tgz",
|
||||
"integrity": "sha512-R4s75XH+o8qM+WaRrAU9S2rbAMDzob18/S3V8R9ZoFpZkPWLAohWWlzWAp1ybeTkOuuku/X1zJtxiV0pBYxZww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
||||
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||
|
@ -67692,6 +67922,34 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"webassembly-floating-point-hex-parser": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/webassembly-floating-point-hex-parser/-/webassembly-floating-point-hex-parser-0.1.2.tgz",
|
||||
"integrity": "sha512-TUf1H++8U10+stJbFydnvrpG5Sznz5Rilez/oZlV5zI0C/e4cSxd8rALAJ8VpTvjVWxLmL3SVSJUK6Ap9AoiNg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"webassembly-interpreter": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/webassembly-interpreter/-/webassembly-interpreter-0.0.30.tgz",
|
||||
"integrity": "sha512-+Jdy2piEvz9T5j751mOE8+rBO12p+nNW6Fg4kJZ+zP1oUfsm+151sbAbM8AFxWTURmWCGP+r8Lxwfv3pzN1bCQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0-beta.36",
|
||||
"long": "^3.2.0",
|
||||
"webassembly-floating-point-hex-parser": "0.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"long": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
|
||||
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
|
||||
|
@ -68494,6 +68752,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"webpack-merge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz",
|
||||
"integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"webpack-sources": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
|
||||
|
|
|
@ -9,16 +9,18 @@
|
|||
"@solana/wallet-base": "^0.0.1",
|
||||
"@solana/web3.js": "^1.22.0",
|
||||
"@typechain/ethers-v5": "^7.0.1",
|
||||
"bridge": "file:rust_modules\\core",
|
||||
"ethers": "^5.4.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3"
|
||||
"react-scripts": "4.0.3",
|
||||
"token-bridge": "file:rust_modules\\token"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "npm run build-contracts",
|
||||
"start": "react-scripts start",
|
||||
"build": "npm run build-contracts && react-scripts build",
|
||||
"test": "npm run build-contracts && react-scripts test",
|
||||
"start": "craco start",
|
||||
"build": "npm run build-contracts && craco build",
|
||||
"test": "npm run build-contracts && craco test",
|
||||
"eject": "react-scripts eject",
|
||||
"build-contracts": "npm run build --prefix ../ethereum && node scripts/copyContracts.js && typechain --target=ethers-v5 --out-dir=src/ethers-contracts contracts/*.json"
|
||||
},
|
||||
|
@ -41,9 +43,11 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@craco/craco": "^6.2.0",
|
||||
"@openzeppelin/contracts": "^4.2.0",
|
||||
"@truffle/hdwallet-provider": "^1.4.1",
|
||||
"copy-dir": "^1.3.0",
|
||||
"truffle": "^5.4.1"
|
||||
"truffle": "^5.4.1",
|
||||
"wasm-loader": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import { useEthereumProvider } from "../contexts/EthereumProviderContext";
|
||||
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
||||
import useEthereumBalance from "../hooks/useEthereumBalance";
|
||||
import useSolanaBalance from "../hooks/useSolanaBalance";
|
||||
import { ChainId, CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "../utils/consts";
|
||||
import EthereumSignerKey from "./EthereumSignerKey";
|
||||
import SolanaWalletKey from "./SolanaWalletKey";
|
||||
|
||||
function KeyAndBalance({
|
||||
chainId,
|
||||
tokenAddress,
|
||||
}: {
|
||||
chainId: ChainId;
|
||||
tokenAddress?: string;
|
||||
}) {
|
||||
// TODO: more generic way to get balance
|
||||
const provider = useEthereumProvider();
|
||||
const ethBalance = useEthereumBalance(
|
||||
tokenAddress,
|
||||
provider,
|
||||
chainId === CHAIN_ID_ETH
|
||||
);
|
||||
const { wallet: solWallet } = useSolanaWallet();
|
||||
const solPK = solWallet?.publicKey;
|
||||
const solBalance = useSolanaBalance(
|
||||
tokenAddress,
|
||||
solPK,
|
||||
chainId === CHAIN_ID_SOLANA
|
||||
);
|
||||
if (chainId === CHAIN_ID_ETH) {
|
||||
return (
|
||||
<>
|
||||
<EthereumSignerKey />
|
||||
<Typography>{ethBalance}</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (chainId === CHAIN_ID_SOLANA) {
|
||||
return (
|
||||
<>
|
||||
<SolanaWalletKey />
|
||||
<Typography>{solBalance}</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export default KeyAndBalance;
|
|
@ -10,16 +10,21 @@ import { useCallback, useState } from "react";
|
|||
import { useEthereumProvider } from "../contexts/EthereumProviderContext";
|
||||
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
||||
import useEthereumBalance from "../hooks/useEthereumBalance";
|
||||
import useSolanaBalance from "../hooks/useSolanaBalance";
|
||||
import {
|
||||
ChainId,
|
||||
CHAINS,
|
||||
CHAINS_BY_ID,
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_SOLANA,
|
||||
ETH_TEST_TOKEN_ADDRESS,
|
||||
SOL_TEST_TOKEN_ADDRESS,
|
||||
} from "../utils/consts";
|
||||
import transferFrom from "../utils/transferFrom";
|
||||
import EthereumSignerKey from "./EthereumSignerKey";
|
||||
import SolanaWalletKey from "./SolanaWalletKey";
|
||||
import transferFrom, {
|
||||
transferFromEth,
|
||||
transferFromSolana,
|
||||
} from "../utils/transferFrom";
|
||||
import KeyAndBalance from "./KeyAndBalance";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
transferBox: {
|
||||
|
@ -57,6 +62,13 @@ function Transfer() {
|
|||
const handleFromChange = useCallback(
|
||||
(event) => {
|
||||
setFromChain(event.target.value);
|
||||
// TODO: remove or check env - for testing purposes
|
||||
if (event.target.value === CHAIN_ID_ETH) {
|
||||
setAssetAddress(ETH_TEST_TOKEN_ADDRESS);
|
||||
}
|
||||
if (event.target.value === CHAIN_ID_SOLANA) {
|
||||
setAssetAddress(SOL_TEST_TOKEN_ADDRESS);
|
||||
}
|
||||
if (toChain === event.target.value) {
|
||||
setToChain(fromChain);
|
||||
}
|
||||
|
@ -68,6 +80,13 @@ function Transfer() {
|
|||
setToChain(event.target.value);
|
||||
if (fromChain === event.target.value) {
|
||||
setFromChain(toChain);
|
||||
// TODO: remove or check env - for testing purposes
|
||||
if (toChain === CHAIN_ID_ETH) {
|
||||
setAssetAddress(ETH_TEST_TOKEN_ADDRESS);
|
||||
}
|
||||
if (toChain === CHAIN_ID_SOLANA) {
|
||||
setAssetAddress(SOL_TEST_TOKEN_ADDRESS);
|
||||
}
|
||||
}
|
||||
},
|
||||
[fromChain, toChain]
|
||||
|
@ -79,22 +98,56 @@ function Transfer() {
|
|||
setAmount(event.target.value);
|
||||
}, []);
|
||||
const provider = useEthereumProvider();
|
||||
const ethBalance = useEthereumBalance(assetAddress, provider);
|
||||
const { wallet } = useSolanaWallet();
|
||||
const solPK = wallet?.publicKey?.toBytes();
|
||||
const solPK = wallet?.publicKey;
|
||||
// TODO: dynamically get "to" wallet
|
||||
const handleClick = useCallback(() => {
|
||||
// TODO: more generic way of calling these
|
||||
if (transferFrom[fromChain]) {
|
||||
transferFrom[fromChain](provider, assetAddress, amount, toChain, solPK);
|
||||
if (
|
||||
fromChain === CHAIN_ID_ETH &&
|
||||
transferFrom[fromChain] === transferFromEth
|
||||
) {
|
||||
transferFromEth(
|
||||
provider,
|
||||
assetAddress,
|
||||
amount,
|
||||
toChain,
|
||||
solPK?.toBytes()
|
||||
);
|
||||
}
|
||||
if (
|
||||
fromChain === CHAIN_ID_SOLANA &&
|
||||
transferFrom[fromChain] === transferFromSolana
|
||||
) {
|
||||
transferFromSolana(
|
||||
solPK?.toString(),
|
||||
assetAddress,
|
||||
amount,
|
||||
provider,
|
||||
toChain
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [fromChain, provider, solPK, assetAddress, amount, toChain]);
|
||||
// update this as we develop, just setting expectations with the button state
|
||||
const ethBalance = useEthereumBalance(
|
||||
assetAddress,
|
||||
provider,
|
||||
fromChain === CHAIN_ID_ETH
|
||||
);
|
||||
const solBalance = useSolanaBalance(
|
||||
assetAddress,
|
||||
solPK,
|
||||
fromChain === CHAIN_ID_SOLANA
|
||||
);
|
||||
const balance = Number(ethBalance) || Number(solBalance);
|
||||
const isTransferImplemented = !!transferFrom[fromChain];
|
||||
const isProviderConnected = !!provider;
|
||||
const isRecipientAvailable = !!solPK;
|
||||
const isAddressDefined = !!assetAddress;
|
||||
const isAmountPositive = Number(amount) > 0; // TODO: this needs per-chain, bn parsing
|
||||
const isBalanceAtLeastAmount = Number(ethBalance) >= Number(amount); // TODO: ditto
|
||||
const isBalanceAtLeastAmount = balance >= Number(amount); // TODO: ditto
|
||||
const canAttemptTransfer =
|
||||
isTransferImplemented &&
|
||||
isProviderConnected &&
|
||||
|
@ -106,7 +159,7 @@ function Transfer() {
|
|||
<div className={classes.transferBox}>
|
||||
<Grid container>
|
||||
<Grid item xs={4}>
|
||||
<Typography>To</Typography>
|
||||
<Typography>From</Typography>
|
||||
<TextField
|
||||
select
|
||||
fullWidth
|
||||
|
@ -119,14 +172,13 @@ function Transfer() {
|
|||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
<EthereumSignerKey />
|
||||
<Typography>{ethBalance}</Typography>
|
||||
<KeyAndBalance chainId={fromChain} tokenAddress={assetAddress} />
|
||||
</Grid>
|
||||
<Grid item xs={4} className={classes.arrow}>
|
||||
→
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<Typography>From</Typography>
|
||||
<Typography>To</Typography>
|
||||
<TextField select fullWidth value={toChain} onChange={handleToChange}>
|
||||
{CHAINS.map(({ id, name }) => (
|
||||
<MenuItem key={id} value={id}>
|
||||
|
@ -134,7 +186,8 @@ function Transfer() {
|
|||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
<SolanaWalletKey />
|
||||
{/* TODO: determine "to" token address */}
|
||||
<KeyAndBalance chainId={toChain} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<TextField
|
||||
|
@ -164,7 +217,7 @@ function Transfer() {
|
|||
{canAttemptTransfer ? null : (
|
||||
<Typography variant="body2" color="error">
|
||||
{!isTransferImplemented
|
||||
? `Transfer is not yet implemented for ${CHAINS[fromChain]}`
|
||||
? `Transfer is not yet implemented for ${CHAINS_BY_ID[fromChain].name}`
|
||||
: !isProviderConnected
|
||||
? "The source wallet is not connected"
|
||||
: !isRecipientAvailable
|
||||
|
@ -175,8 +228,6 @@ function Transfer() {
|
|||
? "The amount must be positive"
|
||||
: !isBalanceAtLeastAmount
|
||||
? "The amount may not be greater than the balance"
|
||||
: !isBalanceAtLeastAmount
|
||||
? "The amount may not be greater than the balance"
|
||||
: ""}
|
||||
</Typography>
|
||||
)}
|
||||
|
|
|
@ -3,35 +3,46 @@ import { formatUnits } from "ethers/lib/utils";
|
|||
import { useEffect, useState } from "react";
|
||||
import { TokenImplementation__factory } from "../ethers-contracts";
|
||||
|
||||
function useEthereumBalance(address: string, provider?: ethers.providers.Web3Provider) {
|
||||
function useEthereumBalance(
|
||||
address: string | undefined,
|
||||
provider: ethers.providers.Web3Provider | undefined,
|
||||
shouldCalculate?: boolean
|
||||
) {
|
||||
//TODO: should this check allowance too or subtract allowance?
|
||||
const [balance, setBalance] = useState<string>('')
|
||||
useEffect(()=>{
|
||||
if (!address || !provider) {
|
||||
setBalance('')
|
||||
return
|
||||
const [balance, setBalance] = useState<string>("");
|
||||
useEffect(() => {
|
||||
if (!address || !provider || !shouldCalculate) {
|
||||
setBalance("");
|
||||
return;
|
||||
}
|
||||
let cancelled = false
|
||||
let cancelled = false;
|
||||
const token = TokenImplementation__factory.connect(address, provider);
|
||||
token.decimals().then((decimals) => {
|
||||
token
|
||||
.decimals()
|
||||
.then((decimals) => {
|
||||
console.log(decimals);
|
||||
provider
|
||||
?.getSigner()
|
||||
.getAddress()
|
||||
.then((pk) => {
|
||||
console.log(pk)
|
||||
console.log(pk);
|
||||
token.balanceOf(pk).then((n) => {
|
||||
if (!cancelled) {
|
||||
setBalance(formatUnits(n,decimals))
|
||||
setBalance(formatUnits(n, decimals));
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setBalance("");
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
},[address, provider])
|
||||
return balance
|
||||
cancelled = true;
|
||||
};
|
||||
}, [address, provider, shouldCalculate]);
|
||||
return balance;
|
||||
}
|
||||
|
||||
export default useEthereumBalance
|
||||
export default useEthereumBalance;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SOLANA_HOST } from "../utils/consts";
|
||||
|
||||
function useSolanaBalance(
|
||||
tokenAddress: string | undefined,
|
||||
ownerAddress: PublicKey | null | undefined,
|
||||
shouldCalculate?: boolean
|
||||
) {
|
||||
//TODO: should connection happen in a context?
|
||||
const [balance, setBalance] = useState<string>("");
|
||||
useEffect(() => {
|
||||
if (!tokenAddress || !ownerAddress || !shouldCalculate) {
|
||||
setBalance("");
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
const connection = new Connection(SOLANA_HOST);
|
||||
connection
|
||||
.getParsedTokenAccountsByOwner(ownerAddress, {
|
||||
mint: new PublicKey(tokenAddress),
|
||||
})
|
||||
.then(({ value }) => {
|
||||
if (!cancelled) {
|
||||
if (value.length) {
|
||||
console.log(value[0].account.data.parsed);
|
||||
setBalance(
|
||||
value[0].account.data.parsed?.info?.tokenAmount?.uiAmountString
|
||||
);
|
||||
} else {
|
||||
setBalance("0");
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setBalance("");
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [tokenAddress, ownerAddress, shouldCalculate]);
|
||||
return balance;
|
||||
}
|
||||
|
||||
export default useSolanaBalance;
|
|
@ -25,6 +25,8 @@ export const CHAINS = [
|
|||
name: 'Terra'
|
||||
},
|
||||
]
|
||||
export type ChainsById = {[key in ChainId]: ChainInfo}
|
||||
export const CHAINS_BY_ID: ChainsById = CHAINS.reduce((obj, chain)=>{obj[chain.id]=chain;return obj},{} as ChainsById)
|
||||
export const SOLANA_HOST = 'http://localhost:8899'
|
||||
export const ETH_TEST_TOKEN_ADDRESS = "0x0290FB167208Af455bB137780163b7B7a9a10C16"
|
||||
export const ETH_TOKEN_BRIDGE_ADDRESS = "0xe982e462b094850f12af94d21d470e21be9d0e9c"
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { ethers } from "ethers";
|
||||
import { formatUnits, parseUnits } from "ethers/lib/utils";
|
||||
import { arrayify, formatUnits, parseUnits } from "ethers/lib/utils";
|
||||
import { Bridge__factory, TokenImplementation__factory } from "../ethers-contracts";
|
||||
import { ChainId, CHAIN_ID_ETH, ETH_TOKEN_BRIDGE_ADDRESS } from "./consts";
|
||||
import { ChainId, CHAIN_ID_ETH, CHAIN_ID_SOLANA, ETH_TOKEN_BRIDGE_ADDRESS, SOL_TOKEN_BRIDGE_ADDRESS } from "./consts";
|
||||
|
||||
// TODO: this should probably be extended from the context somehow so that the signatures match
|
||||
// TODO: allow for / handle cancellation?
|
||||
// TODO: overall better input checking and error handling
|
||||
function transferFromEth(provider: ethers.providers.Web3Provider | undefined, tokenAddress: string, amount: string, recipientChain: ChainId, recipientAddress: Uint8Array | undefined) {
|
||||
export function transferFromEth(provider: ethers.providers.Web3Provider | undefined, tokenAddress: string, amount: string, recipientChain: ChainId, recipientAddress: Uint8Array | undefined) {
|
||||
if (!provider || !recipientAddress) return;
|
||||
const signer = provider.getSigner();
|
||||
if (!signer) return;
|
||||
|
@ -59,8 +59,41 @@ function transferFromEth(provider: ethers.providers.Web3Provider | undefined, to
|
|||
});
|
||||
}
|
||||
|
||||
// TODO: need to check transfer native vs transfer wrapped
|
||||
// TODO: switch out targetProvider for generic address (this likely involves getting these in their respective contexts)
|
||||
export function transferFromSolana(fromAddress: string | undefined, tokenAddress: string, amount: string, targetProvider: ethers.providers.Web3Provider | undefined, targetChain: ChainId) {
|
||||
if (!fromAddress || !targetProvider) return;
|
||||
const targetSigner = targetProvider.getSigner();
|
||||
if (!targetSigner) return;
|
||||
targetSigner.getAddress().then(targetAddressStr => {
|
||||
const targetAddress = arrayify(targetAddressStr)
|
||||
const nonceConst = Math.random() * 100000;
|
||||
const nonceBuffer = Buffer.alloc(4);
|
||||
nonceBuffer.writeUInt32LE(nonceConst, 0);
|
||||
const nonce = nonceBuffer.readUInt32LE(0)
|
||||
// TODO: check decimals
|
||||
// should we avoid BigInt?
|
||||
const amountParsed = BigInt(amount)
|
||||
const fee = BigInt(0) // for now, this won't do anything, we may add later
|
||||
console.log('bridge:',SOL_TOKEN_BRIDGE_ADDRESS)
|
||||
console.log('from:',fromAddress)
|
||||
console.log('token:',tokenAddress)
|
||||
console.log('nonce:',nonce)
|
||||
console.log('amount:',amountParsed)
|
||||
console.log('fee:',fee)
|
||||
console.log('target:',targetAddressStr,targetAddress)
|
||||
console.log('chain:',targetChain)
|
||||
// TODO: program_id vs bridge_id?
|
||||
import("token-bridge").then(({transfer_native_ix})=>{
|
||||
const ix = transfer_native_ix(SOL_TOKEN_BRIDGE_ADDRESS,SOL_TOKEN_BRIDGE_ADDRESS,fromAddress,fromAddress,tokenAddress,nonce,amountParsed,fee,targetAddress,targetChain)
|
||||
console.log(ix)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const transferFrom = {
|
||||
[CHAIN_ID_ETH]: transferFromEth
|
||||
[CHAIN_ID_ETH]: transferFromEth,
|
||||
[CHAIN_ID_SOLANA]: transferFromSolana
|
||||
}
|
||||
|
||||
export default transferFrom
|
|
@ -10,12 +10,20 @@ set -euo pipefail
|
|||
-v $(pwd)/../bridge_ui/rust_modules/core:/usr/src/bridge/bridge/program/pkg \
|
||||
-e EMITTER_ADDRESS=11111111111111111111111111111115 \
|
||||
localhost/certusone/wormhole-wasmpack:latest \
|
||||
/usr/local/cargo/bin/wasm-pack build --target bundler -- --features wasm
|
||||
docker run --rm -it --workdir /usr/src/bridge/bridge/program \
|
||||
-v $(pwd)/../clients/solana/pkg:/usr/src/bridge/bridge/program/pkg \
|
||||
-e EMITTER_ADDRESS=11111111111111111111111111111115 \
|
||||
localhost/certusone/wormhole-wasmpack:latest \
|
||||
/usr/local/cargo/bin/wasm-pack build --target nodejs -- --features wasm
|
||||
cp $(pwd)/../bridge_ui/rust_modules/core/. $(pwd)/../clients/solana/pkg/ -R
|
||||
docker run --rm -it --workdir /usr/src/bridge/modules/token_bridge/program \
|
||||
-v $(pwd)/../bridge_ui/rust_modules/token:/usr/src/bridge/modules/token_bridge/program/pkg \
|
||||
-e EMITTER_ADDRESS=11111111111111111111111111111115 \
|
||||
localhost/certusone/wormhole-wasmpack:latest \
|
||||
/usr/local/cargo/bin/wasm-pack build --target bundler -- --features wasm
|
||||
docker run --rm -it --workdir /usr/src/bridge/modules/token_bridge/program \
|
||||
-v $(pwd)/../clients/token_bridge/pkg:/usr/src/bridge/modules/token_bridge/program/pkg \
|
||||
-e EMITTER_ADDRESS=11111111111111111111111111111115 \
|
||||
localhost/certusone/wormhole-wasmpack:latest \
|
||||
/usr/local/cargo/bin/wasm-pack build --target nodejs -- --features wasm
|
||||
cp $(pwd)/../bridge_ui/rust_modules/. $(pwd)/../clients/token_bridge/pkg -R
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue