Compare commits
47
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61760a180f | ||
|
|
a3f3e160e0 | ||
|
|
b1190914a9 | ||
|
|
e79a952061 | ||
|
|
480ed721d1 | ||
|
|
42c7436827 | ||
|
|
16e9e8b64d | ||
|
|
23ab897e32 | ||
|
|
6fcdec7c12 | ||
|
|
b734f05525 | ||
|
|
30ea9c6bf7 | ||
|
|
6de3a19b86 | ||
|
|
06e59cf916 | ||
|
|
3f3a484a3a | ||
|
|
05e52114bf | ||
|
|
1a421d3b5d | ||
|
|
97fdbc8f64 | ||
|
|
ebf4025718 | ||
|
|
a81a5285b7 | ||
|
|
95c9d56ea4 | ||
|
|
18552f3a22 | ||
|
|
9187e0f2cf | ||
|
|
20d0f53b46 | ||
|
|
0dcb15b7e6 | ||
|
|
ba49a82463 | ||
|
|
8d1b8a47e6 | ||
|
|
b90d3af5b8 | ||
|
|
c34ac468fb | ||
|
|
fefeaeef18 | ||
|
|
91c2352b03 | ||
|
|
9f454d1e08 | ||
|
|
59e5541094 | ||
|
|
8e104b443e | ||
|
|
0eed017bb9 | ||
|
|
789700cf60 | ||
|
|
570d71e8d6 | ||
|
|
961ef644d1 | ||
|
|
6fcd09ddbd | ||
|
|
a9d32f3c90 | ||
|
|
8ec0d00c75 | ||
|
+3 |
0acc530f8b | ||
|
|
7a6f516b4f | ||
|
|
7461e2a914 | ||
|
|
178609a062 | ||
|
|
8ea8f6e954 | ||
|
|
b49efc24ac | ||
|
|
6853e87a49 |
@@ -1,5 +1,35 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 4.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
|
||||
## 4.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1927](https://github.com/thirdweb-dev/js/pull/1927) [`05e52114`](https://github.com/thirdweb-dev/js/commit/05e52114bf4f0ee352f393ed20115a904a18c310) Thanks [@alecananian](https://github.com/alecananian)! - Update Fastify login route response to match Express/Next
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
|
||||
## 4.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`20d0f53b`](https://github.com/thirdweb-dev/js/commit/20d0f53b46a2975a0a14ddaa4a377f2f758804db)]:
|
||||
- @thirdweb-dev/wallets@2.1.1
|
||||
|
||||
## 4.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`0acc530f`](https://github.com/thirdweb-dev/js/commit/0acc530f8bbee59672d9705724edc278bd853d9a)]:
|
||||
- @thirdweb-dev/wallets@2.1.0
|
||||
|
||||
## 4.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "4.1.2",
|
||||
"version": "4.1.6",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -22,7 +22,9 @@ export const loginHandler = (
|
||||
schema: {
|
||||
body: LoginPayloadBodySchema,
|
||||
response: {
|
||||
200: z.any(),
|
||||
200: z.object({
|
||||
token: z.string(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
@@ -104,7 +106,8 @@ export const loginHandler = (
|
||||
},
|
||||
);
|
||||
|
||||
return res.status(200).send({ success: true });
|
||||
// Send token in body and as cookie for frontend and backend use cases
|
||||
return res.status(200).send({ token });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/chains
|
||||
|
||||
## 0.1.58
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1911](https://github.com/thirdweb-dev/js/pull/1911) [`0dcb15b7`](https://github.com/thirdweb-dev/js/commit/0dcb15b7e647acd038b0ec8b1a2b200808aae00e) Thanks [@iketw](https://github.com/iketw)! - Syncs Chains
|
||||
|
||||
## 0.1.57
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -2,7 +2,19 @@ import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "FUSE",
|
||||
"chainId": 122,
|
||||
"explorers": [],
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://explorer.fuse.io",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmYtUimyqHkkFxYdbXXRbUqNg2VLPUg6Uu2C2nmFWowiZM",
|
||||
"width": 551,
|
||||
"height": 540,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
|
||||
@@ -9,7 +9,10 @@ export default {
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"faucets": [
|
||||
"https://faucet.avax.network/?subnet=beam",
|
||||
"https://faucet.onbeam.com"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP1559"
|
||||
@@ -24,15 +27,16 @@ export default {
|
||||
"infoURL": "https://www.onbeam.com",
|
||||
"name": "Beam Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Merit Circle",
|
||||
"symbol": "MC",
|
||||
"name": "Beam",
|
||||
"symbol": "BEAM",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 13337,
|
||||
"rpc": [
|
||||
"https://beam-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://13337.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/beam/testnet/rpc"
|
||||
"https://subnets.avax.network/beam/testnet/rpc",
|
||||
"wss://subnets.avax.network/beam/testnet/ws"
|
||||
],
|
||||
"shortName": "beam-testnet",
|
||||
"slug": "beam-testnet",
|
||||
|
||||
@@ -26,5 +26,6 @@ export default {
|
||||
"shortName": "hmy-s2",
|
||||
"slip44": 1023,
|
||||
"slug": "harmony-shard-2",
|
||||
"status": "deprecated",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -26,5 +26,6 @@ export default {
|
||||
"shortName": "hmy-s3",
|
||||
"slip44": 1023,
|
||||
"slug": "harmony-shard-3",
|
||||
"status": "deprecated",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Roll",
|
||||
"chainId": 1748,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Blockscout",
|
||||
"url": "https://roll.calderaexplorer.xyz/",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmSNKW3HsFekHrTdgt7aAukExwYeYzHZEbG49ZDLYRfkKV/roll_logo%20-%20Ellie%20Li.png",
|
||||
"width": 3600,
|
||||
"height": 3600,
|
||||
"format": ".png"
|
||||
},
|
||||
"infoURL": "https://tryroll.com/",
|
||||
"name": "Roll Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 1748,
|
||||
"redFlags": [],
|
||||
"rpc": [],
|
||||
"shortName": "Roll",
|
||||
"slug": "roll-testnet",
|
||||
"testnet": true,
|
||||
"title": "Roll Testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "okbchain",
|
||||
"chain": "xgon",
|
||||
"chainId": 195,
|
||||
"explorers": [
|
||||
{
|
||||
@@ -14,20 +14,20 @@ export default {
|
||||
],
|
||||
"features": [],
|
||||
"infoURL": "https://www.okx.com/okbc/docs/dev/quick-start/introduction/introduction-to-okbchain",
|
||||
"name": "OKBChain Testnet",
|
||||
"name": "Xgon Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "OKBChain Global Utility Token in testnet",
|
||||
"name": "Xgon Global Utility Token in testnet",
|
||||
"symbol": "OKB",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 195,
|
||||
"rpc": [
|
||||
"https://okbchain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://xgon-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://195.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://okbtestrpc.okbchain.org"
|
||||
"https://testrpc.xgon.io"
|
||||
],
|
||||
"shortName": "tokb",
|
||||
"slug": "okbchain-testnet",
|
||||
"slug": "xgon-testnet",
|
||||
"status": "active",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -1,21 +1,21 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "okbchain",
|
||||
"chain": "xgon",
|
||||
"chainId": 196,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"infoURL": "https://www.okex.com/okc",
|
||||
"name": "OKBChain Mainnet",
|
||||
"infoURL": "https://www.okx.com/okbc/docs/dev/quick-start/introduction/introduction-to-okbchain",
|
||||
"name": "Xgon Mainnet",
|
||||
"nativeCurrency": {
|
||||
"name": "OKBChain Global Utility Token",
|
||||
"name": "Xgon Global Utility Token",
|
||||
"symbol": "OKB",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 196,
|
||||
"rpc": [],
|
||||
"shortName": "okb",
|
||||
"slug": "okbchain",
|
||||
"slug": "xgon",
|
||||
"status": "incubating",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "VinuChain Testnet",
|
||||
"chainId": 206,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "VinuScan Testnet",
|
||||
"url": "https://testnet.vinuscan.com",
|
||||
"standard": "none",
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreiayq7a5qncxzlilfnvpgzt4pwfxbof2qrqr2nyd2suztfummpty4i",
|
||||
"width": 2000,
|
||||
"height": 2000,
|
||||
"format": "jpg"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreidtie4srt52ry67wd3dpxhklmug2ozrawvf3jdlljveinp3frutra",
|
||||
"width": 2000,
|
||||
"height": 392,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://vitainu.org",
|
||||
"name": "VinuChain Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "VinuChain",
|
||||
"symbol": "VС",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 206,
|
||||
"rpc": [
|
||||
"https://vinuchain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://206.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://vinufoundation-rpc.com"
|
||||
],
|
||||
"shortName": "VCTEST",
|
||||
"slug": "vinuchain-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -17,9 +17,9 @@ export default {
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreidtie4srt52ry67wd3dpxhklmug2ozrawvf3jdlljveinp3frutra",
|
||||
"width": 2000,
|
||||
"height": 392,
|
||||
"url": "ipfs://bafybeiderli6uaaxk7eboyf7g4abnybgrkbglmqbkmf25z57ode7zdzmvy",
|
||||
"width": 613,
|
||||
"height": 613,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://vitainu.org",
|
||||
|
||||
@@ -34,10 +34,8 @@ export default {
|
||||
"https://kava.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://2222.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://evm.kava.io",
|
||||
"https://evm2.kava.io",
|
||||
"https://kava-rpc.gateway.pokt.network",
|
||||
"wss://wevm.kava.io",
|
||||
"wss://wevm2.kava.io",
|
||||
"https://kava-evm.publicnode.com",
|
||||
"wss://kava-evm.publicnode.com"
|
||||
],
|
||||
|
||||
@@ -10,11 +10,12 @@ export default {
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmT84suD2ZmTSraJBfeHhTNst2vXctQijNCztok9XiVcUR",
|
||||
"width": 3600,
|
||||
"height": 3600,
|
||||
"format": "png"
|
||||
"url": "ipfs://QmYcGHTPheBwLv9zoJfQAJ7NB6MCtXe2zV7XqPyiTJg3WP/Oasys_Large%20Logo%20Black.png",
|
||||
"width": 1250,
|
||||
"height": 1250,
|
||||
"format": ".png"
|
||||
},
|
||||
"infoURL": "https://oasys.games",
|
||||
"name": "Oasys Mainnet",
|
||||
@@ -24,6 +25,7 @@ export default {
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 248,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://oasys.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://248.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "MCH Verse",
|
||||
"chainId": 29548,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "MCH Verse Explorer",
|
||||
"url": "https://explorer.oasys.mycryptoheroes.net",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmZZnwR1y6cU1sare2TQmwqkNDLXQxD4GdPrmHLmUoPtbU",
|
||||
"width": 4000,
|
||||
"height": 4000,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://www.mycryptoheroes.net/verse",
|
||||
"name": "MCH Verse Mainnet",
|
||||
"nativeCurrency": {
|
||||
"name": "OAS",
|
||||
"symbol": "OAS",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 29548,
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-248"
|
||||
},
|
||||
"rpc": [
|
||||
"https://mch-verse.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://29548.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.oasys.mycryptoheroes.net"
|
||||
],
|
||||
"shortName": "MCHV",
|
||||
"slug": "mch-verse",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "N3-Test",
|
||||
"chainId": 333333,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Nativ3 Test Explorer",
|
||||
"url": "https://scantest.nativ3.network",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmVzJDndPui6qBSeJWe5kMLA56C3KpVhqqqk9xvVKE1DGb",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://nativ3.network",
|
||||
"name": "Nativ3 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "USNT",
|
||||
"symbol": "USNT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 333333,
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-421613",
|
||||
"bridges": [
|
||||
{
|
||||
"url": "https://bridgetest.nativ3.network"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rpc": [
|
||||
"https://nativ3-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://333333.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpctest.nativ3.network",
|
||||
"wss://wstest.nativ3.network"
|
||||
],
|
||||
"shortName": "N3-Test",
|
||||
"slug": "nativ3-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -1,24 +1,24 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "BTC",
|
||||
"chain": "BOTANIX",
|
||||
"chainId": 3636,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Botanix",
|
||||
"url": "https://testnet.btxtestchain.com",
|
||||
"name": "3xpl",
|
||||
"url": "https://3xpl.com/botanix",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.btxtestchain.com"
|
||||
"https://faucet.botanixlabs.dev"
|
||||
],
|
||||
"icon": {
|
||||
"url": "ipfs://Qmf2iSjcrZwUDKhCVY9ZzfbSV2He2HSssbcG2yMz1mDerm",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"url": "ipfs://QmVE5s2pXiqdMnAcxhAmWkZYhpFB5CysypeLyPKzT4rGYe",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://btxtestchain.com",
|
||||
"infoURL": "https://botanixlabs.xyz",
|
||||
"name": "Botanix Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Botanix",
|
||||
@@ -29,9 +29,9 @@ export default {
|
||||
"rpc": [
|
||||
"https://botanix-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://3636.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://testnet-rpc.btxtestchain.com"
|
||||
"https://node.botanixlabs.dev"
|
||||
],
|
||||
"shortName": "BTCt",
|
||||
"shortName": "BTNX",
|
||||
"slug": "botanix-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -13,9 +13,9 @@ export default {
|
||||
"https://faucet.btxtestchain.com"
|
||||
],
|
||||
"icon": {
|
||||
"url": "ipfs://Qmf2iSjcrZwUDKhCVY9ZzfbSV2He2HSssbcG2yMz1mDerm",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"url": "ipfs://QmVE5s2pXiqdMnAcxhAmWkZYhpFB5CysypeLyPKzT4rGYe",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://btxtestchain.com",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Nativ3",
|
||||
"chainId": 399,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "N3scan",
|
||||
"url": "https://scan.nativ3.network",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmVzJDndPui6qBSeJWe5kMLA56C3KpVhqqqk9xvVKE1DGb",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://nativ3.network",
|
||||
"name": "Nativ3 Mainnet",
|
||||
"nativeCurrency": {
|
||||
"name": "USNT",
|
||||
"symbol": "USNT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 399,
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-42161",
|
||||
"bridges": [
|
||||
{
|
||||
"url": "https://bridge.nativ3.network"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rpc": [
|
||||
"https://nativ3.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://399.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.nativ3.network",
|
||||
"wss://ws.nativ3.network"
|
||||
],
|
||||
"shortName": "N3",
|
||||
"slug": "nativ3",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -9,7 +9,9 @@ export default {
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"faucets": [
|
||||
"https://faucet.onbeam.com"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP1559"
|
||||
@@ -24,15 +26,16 @@ export default {
|
||||
"infoURL": "https://www.onbeam.com",
|
||||
"name": "Beam",
|
||||
"nativeCurrency": {
|
||||
"name": "Merit Circle",
|
||||
"symbol": "MC",
|
||||
"name": "Beam",
|
||||
"symbol": "BEAM",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 4337,
|
||||
"rpc": [
|
||||
"https://beam.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://4337.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/beam/mainnet/rpc"
|
||||
"https://subnets.avax.network/beam/mainnet/rpc",
|
||||
"wss://subnets.avax.network/beam/mainnet/ws"
|
||||
],
|
||||
"shortName": "beam",
|
||||
"slug": "beam",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "ETH",
|
||||
"chainId": 5003,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://explorer.sepolia.mantle.xyz",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.sepolia.mantle.xyz"
|
||||
],
|
||||
"infoURL": "https://mantle.xyz",
|
||||
"name": "Mantle Sepolia Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Sepolia Mantle",
|
||||
"symbol": "MNT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 5003,
|
||||
"rpc": [
|
||||
"https://mantle-sepolia-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://5003.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.sepolia.mantle.xyz"
|
||||
],
|
||||
"shortName": "mnt-sep",
|
||||
"slug": "mantle-sepolia-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Electroneum",
|
||||
"chainId": 52014,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://blockexplorer.electroneum.com",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmVgFqXA3kkCrVYGcWFF7Mhx8JUSe9vSCauNamuKWSvCym",
|
||||
"width": 1000,
|
||||
"height": 1000,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"icon": {
|
||||
"url": "ipfs://QmVgFqXA3kkCrVYGcWFF7Mhx8JUSe9vSCauNamuKWSvCym",
|
||||
"width": 1000,
|
||||
"height": 1000,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://electroneum.com",
|
||||
"name": "Electroneum Mainnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Electroneum",
|
||||
"symbol": "ETN",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 52014,
|
||||
"rpc": [
|
||||
"https://electroneum.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://52014.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://api.electroneum.com"
|
||||
],
|
||||
"shortName": "etn-mainnet",
|
||||
"slug": "electroneum",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Electroneum",
|
||||
"chainId": 5201420,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://blockexplorer.thesecurityteam.rocks",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmVgFqXA3kkCrVYGcWFF7Mhx8JUSe9vSCauNamuKWSvCym",
|
||||
"width": 1000,
|
||||
"height": 1000,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"icon": {
|
||||
"url": "ipfs://QmVgFqXA3kkCrVYGcWFF7Mhx8JUSe9vSCauNamuKWSvCym",
|
||||
"width": 1000,
|
||||
"height": 1000,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://electroneum.com",
|
||||
"name": "Electroneum Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Electroneum",
|
||||
"symbol": "ETN",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 5201420,
|
||||
"rpc": [
|
||||
"https://electroneum-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://5201420.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://api.electroneum.com"
|
||||
],
|
||||
"shortName": "etn-testnet",
|
||||
"slug": "electroneum-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -25,8 +25,7 @@ export default {
|
||||
"https://570.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.rollux.com",
|
||||
"https://rollux.public-rpc.com",
|
||||
"wss://rpc.rollux.com/wss",
|
||||
"https://rpc.ankr.com/rollux/${ANKR_API_KEY}"
|
||||
"wss://rpc.rollux.com/wss"
|
||||
],
|
||||
"shortName": "sys-rollux",
|
||||
"slug": "rollux",
|
||||
|
||||
@@ -13,6 +13,12 @@ export default {
|
||||
"https://faucet.triangleplatform.com/frame"
|
||||
],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmTS1P9sh49zg5xL5BUsRLWDz3vVoJCtCNf9yN1TTnsuQ3",
|
||||
"width": 321,
|
||||
"height": 320,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://frame.xyz",
|
||||
"name": "Frame Testnet",
|
||||
"nativeCurrency": {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "TWT",
|
||||
"chainId": 894538,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "explorer",
|
||||
"url": "https://subnets-test.avax.network/thirdweb",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmXDGoJKuuwQKzY1Y7ZhgULg8hcmveu6PVaDaYQzEjKwkQ/Thirdweb-Icon-Black-BG.png",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"name": "thirdweb test subnet",
|
||||
"nativeCurrency": {
|
||||
"name": "TWT",
|
||||
"symbol": "TWT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 894538,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://thirdweb-test-subnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://894538.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/thirdweb/testnet/rpc"
|
||||
],
|
||||
"shortName": "twt",
|
||||
"slug": "thirdweb-test-subnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "XCAP",
|
||||
"chainId": 9322252,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://xcap-mainnet.explorer.xcap.network",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmYtUimyqHkkFxYdbXXRbUqNg2VLPUg6Uu2C2nmFWowiZM",
|
||||
"width": 551,
|
||||
"height": 540,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmeTj6tfaw9qf9wnEUQh7PnCpNWyvm56e7kY35kANRWNxj",
|
||||
"width": 1600,
|
||||
"height": 1600,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://xcap.network/",
|
||||
"name": "XCAP",
|
||||
"nativeCurrency": {
|
||||
"name": "Gas",
|
||||
"symbol": "GAS",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 9322252,
|
||||
"rpc": [
|
||||
"https://xcap.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://9322252.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://xcap-mainnet.relay.xcap.network/znzvh2ueyvm2yts5fv5gnul395jbkfb2/rpc1"
|
||||
],
|
||||
"shortName": "xcap",
|
||||
"slug": "xcap",
|
||||
"testnet": false,
|
||||
"title": "XCAP Mainnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "XCAP",
|
||||
"chainId": 9322253,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://xcap-milvine.explorer.xcap.network",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmYtUimyqHkkFxYdbXXRbUqNg2VLPUg6Uu2C2nmFWowiZM",
|
||||
"width": 551,
|
||||
"height": 540,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmeTj6tfaw9qf9wnEUQh7PnCpNWyvm56e7kY35kANRWNxj",
|
||||
"width": 1600,
|
||||
"height": 1600,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://xcap.network/",
|
||||
"name": "Milvine",
|
||||
"nativeCurrency": {
|
||||
"name": "Gas",
|
||||
"symbol": "GAS",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 9322253,
|
||||
"rpc": [
|
||||
"https://milvine.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://9322253.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://xcap-milvine.relay.xcap.network/zj5l55ftsgi027kz4nf14vs8d89inego/rpc1"
|
||||
],
|
||||
"shortName": "milv",
|
||||
"slug": "milvine",
|
||||
"testnet": true,
|
||||
"title": "XCAP Testnet Milvine"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Ecrox Chain",
|
||||
"chainId": 988207,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Ecrox Chain Explorer",
|
||||
"url": "https://ecroxscan.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreibnqdlwgotu4hwx6oeu4ye3huobr3eaiuvv55n5tolyxya2q7edmq",
|
||||
"width": 300,
|
||||
"height": 300,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://ecroxcoin.io/",
|
||||
"name": "Ecrox Chain Mainnet",
|
||||
"nativeCurrency": {
|
||||
"name": "ECROX COIN",
|
||||
"symbol": "ECROX",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 988207,
|
||||
"rpc": [
|
||||
"https://ecrox-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://988207.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://mainnet-rpc.ecroxscan.com/"
|
||||
],
|
||||
"shortName": "ecrox",
|
||||
"slug": "ecrox-chain",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/chains",
|
||||
"version": "0.1.57",
|
||||
"version": "0.1.58",
|
||||
"main": "dist/thirdweb-dev-chains.cjs.js",
|
||||
"module": "dist/thirdweb-dev-chains.esm.js",
|
||||
"browser": {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,46 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.13.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`23ab897e`](https://github.com/thirdweb-dev/js/commit/23ab897e329cdd5b316fbe554ea0f64add91f2b4), [`a3f3e160`](https://github.com/thirdweb-dev/js/commit/a3f3e160e07328655a4f0332f41f4edd210a1a8a), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/sdk@4.0.13
|
||||
- @thirdweb-dev/storage@2.0.4
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
- @thirdweb-dev/auth@4.1.6
|
||||
|
||||
## 0.13.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1918](https://github.com/thirdweb-dev/js/pull/1918) [`95c9d56e`](https://github.com/thirdweb-dev/js/commit/95c9d56ea47ef57113679196efe8f9114c6fbb21) Thanks [@saminacodes](https://github.com/saminacodes)! - Fix url redirect for pre-built deploy command
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`05e52114`](https://github.com/thirdweb-dev/js/commit/05e52114bf4f0ee352f393ed20115a904a18c310), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8), [`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
- @thirdweb-dev/auth@4.1.5
|
||||
- @thirdweb-dev/storage@2.0.3
|
||||
- @thirdweb-dev/sdk@4.0.12
|
||||
|
||||
## 0.13.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`0dcb15b7`](https://github.com/thirdweb-dev/js/commit/0dcb15b7e647acd038b0ec8b1a2b200808aae00e), [`fefeaeef`](https://github.com/thirdweb-dev/js/commit/fefeaeef18f52a75462c43da8b85a77975d32e01), [`20d0f53b`](https://github.com/thirdweb-dev/js/commit/20d0f53b46a2975a0a14ddaa4a377f2f758804db), [`91c2352b`](https://github.com/thirdweb-dev/js/commit/91c2352b03d7cf1c3cbbbc98846f248b0f707ea7)]:
|
||||
- @thirdweb-dev/chains@0.1.58
|
||||
- @thirdweb-dev/sdk@4.0.11
|
||||
- @thirdweb-dev/wallets@2.1.1
|
||||
- @thirdweb-dev/auth@4.1.4
|
||||
|
||||
## 0.13.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a9d32f3c`](https://github.com/thirdweb-dev/js/commit/a9d32f3c90251a459e17a19eca803bbfdeeaeb79), [`0acc530f`](https://github.com/thirdweb-dev/js/commit/0acc530f8bbee59672d9705724edc278bd853d9a)]:
|
||||
- @thirdweb-dev/sdk@4.0.10
|
||||
- @thirdweb-dev/wallets@2.1.0
|
||||
- @thirdweb-dev/auth@4.1.3
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.13.10",
|
||||
"version": "0.13.14",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -30,7 +30,7 @@ export default function generateDashboardUrl(
|
||||
const foundMapping = mapping[name as keyof typeof mapping];
|
||||
|
||||
return foundMapping
|
||||
? `https://thirdweb.com/dashboard/${foundMapping}`
|
||||
? `https://thirdweb.com/thirdweb.eth/${foundMapping}`
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
plugins: ["better-tree-shaking"],
|
||||
plugins: ["better-tree-shaking", "eslint-plugin-tsdoc"],
|
||||
rules: {
|
||||
"tsdoc/syntax": "error",
|
||||
"better-tree-shaking/no-top-level-side-effects": "error",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,56 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 4.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1951](https://github.com/thirdweb-dev/js/pull/1951) [`e79a9520`](https://github.com/thirdweb-dev/js/commit/e79a95206116ea09de0126fdbe30fb4413fdff28) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Fix caching issue with useTotalCirculatingSupply
|
||||
|
||||
- [#1944](https://github.com/thirdweb-dev/js/pull/1944) [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- [#1950](https://github.com/thirdweb-dev/js/pull/1950) [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Smart Wallet autoconnect fixes and performance improvements
|
||||
|
||||
- Updated dependencies [[`23ab897e`](https://github.com/thirdweb-dev/js/commit/23ab897e329cdd5b316fbe554ea0f64add91f2b4), [`a3f3e160`](https://github.com/thirdweb-dev/js/commit/a3f3e160e07328655a4f0332f41f4edd210a1a8a), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/sdk@4.0.13
|
||||
- @thirdweb-dev/storage@2.0.4
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
- @thirdweb-dev/auth@4.1.6
|
||||
|
||||
## 4.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1943](https://github.com/thirdweb-dev/js/pull/1943) [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- [#1929](https://github.com/thirdweb-dev/js/pull/1929) [`06e59cf9`](https://github.com/thirdweb-dev/js/commit/06e59cf91647e4080829d49f8cb91a4d8fdc87f7) Thanks [@iketw](https://github.com/iketw)! - Move addresses' utils to the core package
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`05e52114`](https://github.com/thirdweb-dev/js/commit/05e52114bf4f0ee352f393ed20115a904a18c310), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8), [`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
- @thirdweb-dev/auth@4.1.5
|
||||
- @thirdweb-dev/storage@2.0.3
|
||||
- @thirdweb-dev/sdk@4.0.12
|
||||
|
||||
## 4.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`0dcb15b7`](https://github.com/thirdweb-dev/js/commit/0dcb15b7e647acd038b0ec8b1a2b200808aae00e), [`fefeaeef`](https://github.com/thirdweb-dev/js/commit/fefeaeef18f52a75462c43da8b85a77975d32e01), [`20d0f53b`](https://github.com/thirdweb-dev/js/commit/20d0f53b46a2975a0a14ddaa4a377f2f758804db), [`91c2352b`](https://github.com/thirdweb-dev/js/commit/91c2352b03d7cf1c3cbbbc98846f248b0f707ea7)]:
|
||||
- @thirdweb-dev/chains@0.1.58
|
||||
- @thirdweb-dev/sdk@4.0.11
|
||||
- @thirdweb-dev/wallets@2.1.1
|
||||
- @thirdweb-dev/auth@4.1.4
|
||||
|
||||
## 4.1.1
|
||||
|
||||
## 4.1.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a9d32f3c`](https://github.com/thirdweb-dev/js/commit/a9d32f3c90251a459e17a19eca803bbfdeeaeb79), [`0acc530f`](https://github.com/thirdweb-dev/js/commit/0acc530f8bbee59672d9705724edc278bd853d9a)]:
|
||||
- @thirdweb-dev/sdk@4.0.10
|
||||
- @thirdweb-dev/wallets@2.1.0
|
||||
- @thirdweb-dev/auth@4.1.3
|
||||
|
||||
## 4.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "4.0.10",
|
||||
"version": "4.1.4",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -3,6 +3,7 @@ import invariant from "tiny-invariant";
|
||||
import type {
|
||||
BloctoWallet,
|
||||
CoinbaseWallet,
|
||||
CoreWallet,
|
||||
EmbeddedWallet,
|
||||
FrameWallet,
|
||||
LocalWallet,
|
||||
@@ -26,6 +27,7 @@ export type WalletId = (typeof walletIds)[keyof typeof walletIds];
|
||||
type WalletIdToWalletTypeMap = {
|
||||
metamask: MetaMaskWallet;
|
||||
coinbase: CoinbaseWallet;
|
||||
coreWallet: CoreWallet;
|
||||
rainbowWallet: RainbowWallet;
|
||||
blocto: BloctoWallet;
|
||||
frame: FrameWallet;
|
||||
|
||||
@@ -199,7 +199,7 @@ export function ThirdwebWalletProvider(
|
||||
|
||||
const walletInfo: LastConnectedWalletInfo = {
|
||||
walletId: walletConfig.id,
|
||||
connectParams,
|
||||
connectParams: connectParams || wallet.getConnectParams(),
|
||||
};
|
||||
|
||||
// if personal wallet exists, we need to replace the connectParams.personalWallet to a stringifiable version
|
||||
@@ -335,7 +335,7 @@ export function ThirdwebWalletProvider(
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Failed to auto connect wallet");
|
||||
console.error("Failed to auto connect personal wallet");
|
||||
console.error(e);
|
||||
setConnectionStatus("disconnected");
|
||||
return;
|
||||
@@ -366,9 +366,14 @@ export function ThirdwebWalletProvider(
|
||||
} catch (e) {
|
||||
console.error("Failed to auto connect wallet");
|
||||
console.error(e);
|
||||
lastConnectedWalletStorage.removeItem(
|
||||
LAST_CONNECTED_WALLET_STORAGE_KEY,
|
||||
);
|
||||
if (
|
||||
e instanceof Error &&
|
||||
e.message === autoConnectTimeoutErrorMessage
|
||||
) {
|
||||
lastConnectedWalletStorage.removeItem(
|
||||
LAST_CONNECTED_WALLET_STORAGE_KEY,
|
||||
);
|
||||
}
|
||||
setConnectionStatus("disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,13 @@ export type WalletConfig<I extends WalletInstance = WalletInstance> = {
|
||||
|
||||
/**
|
||||
* If true, this wallet will be tagged as "recommended" in ConnectWallet Modal and will be shown at the top of the list
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
recommended?: boolean;
|
||||
|
||||
/**
|
||||
* If the wallet can sign transactions without user interaction, set this to true.
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
isHeadless?: boolean;
|
||||
};
|
||||
@@ -154,7 +154,7 @@ export type ConnectUIProps<I extends WalletInstance = WalletInstance> = {
|
||||
/**
|
||||
* Called when the wallet is connected but it's
|
||||
* part of another wallet's connection flow.
|
||||
* @param walleInstance the instance of the connected wallet
|
||||
* @param walleInstance - the instance of the connected wallet
|
||||
*/
|
||||
onLocallyConnected?: (walleInstance: WalletInstance) => void;
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ import { constants, utils } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
/**
|
||||
* The options to be passed as the second parameter to the {@link useClaimIneligibilityReasons}` hook.
|
||||
* The options to be passed as the second parameter to the {@link useClaimIneligibilityReasons} hook.
|
||||
*
|
||||
* @beta
|
||||
*/
|
||||
|
||||
@@ -193,7 +193,10 @@ export function useTotalCirculatingSupply(
|
||||
const { erc721, erc1155 } = getErcs(contract);
|
||||
|
||||
return useQueryWithNetwork<BigNumber>(
|
||||
cacheKeys.contract.nft.query.totalCirculatingSupply(contractAddress),
|
||||
cacheKeys.contract.nft.query.totalCirculatingSupply(
|
||||
contractAddress,
|
||||
tokenId ?? undefined,
|
||||
),
|
||||
async () => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
|
||||
@@ -718,7 +721,7 @@ export function useBurnNFT<TContract extends NFTContract>(
|
||||
/**
|
||||
* Set shared metadata
|
||||
* TODO add docs
|
||||
* @private
|
||||
* @internal
|
||||
*/
|
||||
export function useSetSharedMetadata<TContract extends NFTContract>(
|
||||
contract: RequiredParam<TContract>,
|
||||
|
||||
@@ -257,6 +257,13 @@ export type { ThirdwebSDKProviderProps } from "./providers/types";
|
||||
|
||||
// utils
|
||||
export { invalidateContractAndBalances } from "./utils/cache-keys";
|
||||
export {
|
||||
isEnsName,
|
||||
isPossibleEVMAddress,
|
||||
shortenAddress,
|
||||
shortenIfAddress,
|
||||
shortenString,
|
||||
} from "./utils/addresses";
|
||||
|
||||
// types
|
||||
export type {
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import { utils } from "ethers";
|
||||
|
||||
export function shortenString(str: string, extraShort?: true) {
|
||||
export function shortenString(str: string, extraShort: boolean = true) {
|
||||
return `${str.substring(0, extraShort ? 4 : 6)}...${str.substring(
|
||||
str.length - (extraShort ? 3 : 4),
|
||||
)}`;
|
||||
}
|
||||
|
||||
export function shortenAddress(address: string, extraShort?: true): string {
|
||||
/**
|
||||
* This function shortens an address if it is a valid EVM address.
|
||||
*
|
||||
* @param address - The address to shorten
|
||||
* @param extraShort - If true, show the first 4 and last 3 characters
|
||||
* @returns The shortened address
|
||||
*
|
||||
* @remarks
|
||||
* Note that this function will not check if the address is an ENS.
|
||||
*
|
||||
* @example Calling shortenAddress with extraShort set to true
|
||||
* ```ts
|
||||
* const address = shortenIfAddress("0x1234567890123456789012345678901234567890", true); // result will be "0x1234...890"
|
||||
* ```
|
||||
*/
|
||||
export function shortenAddress(
|
||||
address?: string,
|
||||
extraShort: boolean = true,
|
||||
): string {
|
||||
if (!address) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
const formattedAddress = utils.getAddress(address);
|
||||
return shortenString(formattedAddress, extraShort);
|
||||
@@ -17,10 +38,24 @@ export function shortenAddress(address: string, extraShort?: true): string {
|
||||
|
||||
export function shortenIfAddress(
|
||||
address?: string | null | false,
|
||||
extraShort?: true,
|
||||
extraShort: boolean = true,
|
||||
): string {
|
||||
if (typeof address === "string" && address.length > 0) {
|
||||
if (address && utils.isAddress(address)) {
|
||||
return shortenAddress(address, extraShort);
|
||||
}
|
||||
return address || "";
|
||||
}
|
||||
|
||||
export function isEnsName(name: string): boolean {
|
||||
return name?.endsWith(".eth");
|
||||
}
|
||||
|
||||
export function isPossibleEVMAddress(address?: string, ignoreEns?: boolean) {
|
||||
if (!address) {
|
||||
return false;
|
||||
}
|
||||
if (isEnsName(address) && !ignoreEns) {
|
||||
return true;
|
||||
}
|
||||
return utils.isAddress(address);
|
||||
}
|
||||
|
||||
@@ -182,10 +182,12 @@ export const cacheKeys = {
|
||||
),
|
||||
totalCirculatingSupply: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
) =>
|
||||
createContractCacheKey(contractAddress, [
|
||||
"query",
|
||||
"totalCirculatingSupply",
|
||||
tokenId ?? "0",
|
||||
]),
|
||||
totalCount: (contractAddress: RequiredParam<ContractAddress>) =>
|
||||
createContractCacheKey(contractAddress, ["query", "totalCount"]),
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.4.4
|
||||
|
||||
## 0.4.3
|
||||
|
||||
## 0.4.2
|
||||
|
||||
## 0.4.1
|
||||
|
||||
## 0.4.0
|
||||
|
||||
## 0.3.16
|
||||
|
||||
## 0.3.15
|
||||
|
||||
## 0.3.14
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.3.15",
|
||||
"version": "0.4.4",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
plugins: ["i18next"],
|
||||
plugins: ["i18next", "eslint-plugin-tsdoc"],
|
||||
rules: {
|
||||
"tsdoc/syntax": "error",
|
||||
"i18next/no-literal-string": 2,
|
||||
},
|
||||
settings: {
|
||||
|
||||
@@ -1,5 +1,236 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.4.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1944](https://github.com/thirdweb-dev/js/pull/1944) [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- Updated dependencies [[`23ab897e`](https://github.com/thirdweb-dev/js/commit/23ab897e329cdd5b316fbe554ea0f64add91f2b4), [`a3f3e160`](https://github.com/thirdweb-dev/js/commit/a3f3e160e07328655a4f0332f41f4edd210a1a8a), [`e79a9520`](https://github.com/thirdweb-dev/js/commit/e79a95206116ea09de0126fdbe30fb4413fdff28), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/sdk@4.0.13
|
||||
- @thirdweb-dev/react-core@4.1.4
|
||||
- @thirdweb-dev/storage@2.0.4
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
|
||||
## 0.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1908](https://github.com/thirdweb-dev/js/pull/1908) [`18552f3a`](https://github.com/thirdweb-dev/js/commit/18552f3a225d1c46f0ff19c2b1c9cc44f84e33ac) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Add `hideSwitchToPersonalWallet` prop on `ConnectWallet` component to hide the "Switch to Personal wallet" option in the ConnectWallet modal which is shown when wallet is connected as a Smart Wallet
|
||||
|
||||
- [#1912](https://github.com/thirdweb-dev/js/pull/1912) [`1a421d3b`](https://github.com/thirdweb-dev/js/commit/1a421d3b5d837eade5b7344118a7148ddea35517) Thanks [@iketw](https://github.com/iketw)! - Adds Apple as a social sign in option for EmbeddedWallet
|
||||
|
||||
You can now do:
|
||||
|
||||
```typescript
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ['apple'],
|
||||
redirectUrl: 'your-apps-redirect-url://',
|
||||
},
|
||||
}),
|
||||
```
|
||||
|
||||
- [#1943](https://github.com/thirdweb-dev/js/pull/1943) [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- [#1929](https://github.com/thirdweb-dev/js/pull/1929) [`06e59cf9`](https://github.com/thirdweb-dev/js/commit/06e59cf91647e4080829d49f8cb91a4d8fdc87f7) Thanks [@iketw](https://github.com/iketw)! - Move addresses' utils to the core package
|
||||
|
||||
- [#1925](https://github.com/thirdweb-dev/js/pull/1925) [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8) Thanks [@iketw](https://github.com/iketw)! - [RN] Adds walletConnectReceiver prop to EmbeddedWallet and SmartWallet
|
||||
|
||||
You can pass your own WalletConnect projectId and metadata (highly recommended):
|
||||
|
||||
```typescript
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ['email', 'google'],
|
||||
redirectUrl: 'redirect-url',
|
||||
},
|
||||
walletConnectReceiver: {
|
||||
walletConnectWalletMetadata?: WCMetadata;
|
||||
walletConnectV2ProjectId?: string;
|
||||
walletConnectV2RelayUrl?: string;
|
||||
},
|
||||
}),
|
||||
|
||||
smartWallet(localWallet(), {
|
||||
factoryAddress: 'factory-address',
|
||||
gasless: true,
|
||||
walletConnectReceiver: {
|
||||
walletConnectWalletMetadata?: WCMetadata;
|
||||
walletConnectV2ProjectId?: string;
|
||||
walletConnectV2RelayUrl?: string;
|
||||
},
|
||||
}),
|
||||
```
|
||||
|
||||
You can just pass `true` to the prop and these props will default to our internal WalletConnect projectId and metadata.
|
||||
|
||||
```typescript
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ['email', 'google'],
|
||||
redirectUrl: 'redirect-url',
|
||||
},
|
||||
walletConnectReceiver: true
|
||||
}),
|
||||
|
||||
smartWallet(localWallet(), {
|
||||
factoryAddress: 'factory-address',
|
||||
gasless: true,
|
||||
walletConnectReceiver: true
|
||||
}),
|
||||
```
|
||||
|
||||
- [#1942](https://github.com/thirdweb-dev/js/pull/1942) [`6de3a19b`](https://github.com/thirdweb-dev/js/commit/6de3a19b86476cf5f7d67223a366379c4fdb9b74) Thanks [@iketw](https://github.com/iketw)! - Updated react-native-safe-area-context to 4.74
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`06e59cf9`](https://github.com/thirdweb-dev/js/commit/06e59cf91647e4080829d49f8cb91a4d8fdc87f7), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8), [`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
- @thirdweb-dev/react-core@4.1.3
|
||||
- @thirdweb-dev/storage@2.0.3
|
||||
- @thirdweb-dev/sdk@4.0.12
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1893](https://github.com/thirdweb-dev/js/pull/1893) [`8e104b44`](https://github.com/thirdweb-dev/js/commit/8e104b443e4a11908be660656c525ad237115835) Thanks [@iketw](https://github.com/iketw)! - Updates Japanese translations
|
||||
|
||||
- [#1893](https://github.com/thirdweb-dev/js/pull/1893) [`8e104b44`](https://github.com/thirdweb-dev/js/commit/8e104b443e4a11908be660656c525ad237115835) Thanks [@iketw](https://github.com/iketw)! - Adds support for Japanese and Spanish
|
||||
|
||||
You can now pass 'ja' or 'es' to our ThirdwebProvider:
|
||||
|
||||
```
|
||||
import { ThirdwebProvider } from '@thirdweb-dev/react-native';
|
||||
|
||||
<ThirdwebProvider locale={'ja'}>
|
||||
<App />
|
||||
</ ThirdwebProvider>
|
||||
```
|
||||
|
||||
- [#1892](https://github.com/thirdweb-dev/js/pull/1892) [`59e55410`](https://github.com/thirdweb-dev/js/commit/59e55410942f3cb08570623f990487868aaed107) Thanks [@iketw](https://github.com/iketw)! - Deprecates magicLink in favor of embedded wallet
|
||||
|
||||
- [#1900](https://github.com/thirdweb-dev/js/pull/1900) [`9f454d1e`](https://github.com/thirdweb-dev/js/commit/9f454d1e08ebf5280a3266791d1843ddd7e24242) Thanks [@iketw](https://github.com/iketw)! - Export Locale types and improve modal title customization
|
||||
|
||||
- [#1909](https://github.com/thirdweb-dev/js/pull/1909) [`ba49a824`](https://github.com/thirdweb-dev/js/commit/ba49a82463487735dc19bf33ab2f7a3e9cce08ac) Thanks [@iketw](https://github.com/iketw)! - UI improvements
|
||||
|
||||
- Updated dependencies [[`0dcb15b7`](https://github.com/thirdweb-dev/js/commit/0dcb15b7e647acd038b0ec8b1a2b200808aae00e), [`fefeaeef`](https://github.com/thirdweb-dev/js/commit/fefeaeef18f52a75462c43da8b85a77975d32e01), [`20d0f53b`](https://github.com/thirdweb-dev/js/commit/20d0f53b46a2975a0a14ddaa4a377f2f758804db), [`91c2352b`](https://github.com/thirdweb-dev/js/commit/91c2352b03d7cf1c3cbbbc98846f248b0f707ea7)]:
|
||||
- @thirdweb-dev/chains@0.1.58
|
||||
- @thirdweb-dev/sdk@4.0.11
|
||||
- @thirdweb-dev/wallets@2.1.1
|
||||
- @thirdweb-dev/react-core@4.1.2
|
||||
|
||||
## 0.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/react-core@4.1.1
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1846](https://github.com/thirdweb-dev/js/pull/1846) [`0acc530f`](https://github.com/thirdweb-dev/js/commit/0acc530f8bbee59672d9705724edc278bd853d9a) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - New API to configure authentication options on `embeddedWallet`
|
||||
|
||||
```ts
|
||||
// default - google sign in is enabled
|
||||
embeddedWallet();
|
||||
|
||||
// this is same as
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ["email"],
|
||||
},
|
||||
});
|
||||
|
||||
// add google sign in
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ["email", "google"],
|
||||
redirectUrl: "your_app://deeplink",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1885](https://github.com/thirdweb-dev/js/pull/1885) [`961ef644`](https://github.com/thirdweb-dev/js/commit/961ef644d1b1adaad08c071903cd53aacac50bb4) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Improved `useSmartWallet()` hook
|
||||
|
||||
Example with metamask:
|
||||
|
||||
```ts
|
||||
const { connect } = useSmartWallet(metamaskWallet(), {
|
||||
factoryAddress: factoryAddress,
|
||||
gasless: true,
|
||||
});
|
||||
|
||||
const onClick = async () => {
|
||||
// nothing to do here, all handled internally
|
||||
await connect();
|
||||
};
|
||||
```
|
||||
|
||||
```ts
|
||||
Example with localWallet:
|
||||
|
||||
const { connect } = useSmartWallet(localWallet(), {
|
||||
factoryAddress: factoryAddress,
|
||||
gasless: true,
|
||||
});
|
||||
|
||||
const onClick = async () => {
|
||||
// function to 'load' the local wallet before using it
|
||||
await connect({
|
||||
connectPersonalWallet: async (w) => {
|
||||
await w.generate();
|
||||
await w.connect();
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
Example with embeddedWallet:
|
||||
|
||||
const { connect } = useSmartWallet(embeddedWallet(), {
|
||||
factoryAddress: factoryAddress,
|
||||
gasless: true,
|
||||
});
|
||||
|
||||
const onClick = async () => {
|
||||
// function to 'auth' the embedded wallet before using it
|
||||
await connect({
|
||||
connectPersonalWallet: async (w) => {
|
||||
const authResult = await w.authenticate({ strategy: "google" });
|
||||
await w.connect({ authResult });
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
- Updated dependencies [[`a9d32f3c`](https://github.com/thirdweb-dev/js/commit/a9d32f3c90251a459e17a19eca803bbfdeeaeb79), [`0acc530f`](https://github.com/thirdweb-dev/js/commit/0acc530f8bbee59672d9705724edc278bd853d9a)]:
|
||||
- @thirdweb-dev/sdk@4.0.10
|
||||
- @thirdweb-dev/wallets@2.1.0
|
||||
- @thirdweb-dev/react-core@4.1.0
|
||||
|
||||
## 0.3.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1880](https://github.com/thirdweb-dev/js/pull/1880) [`7461e2a9`](https://github.com/thirdweb-dev/js/commit/7461e2a9145549b7e08bc34d87d44be9bcff2c07) Thanks [@iketw](https://github.com/iketw)! - Fixes wallet icons borders bug
|
||||
|
||||
- [#1878](https://github.com/thirdweb-dev/js/pull/1878) [`178609a0`](https://github.com/thirdweb-dev/js/commit/178609a0622b571560188a4266247eb342759ea1) Thanks [@iketw](https://github.com/iketw)! - Adds support for Japanese and Spanish
|
||||
|
||||
You can now pass 'ja' or 'es' to our ThirdwebProvider:
|
||||
|
||||
```
|
||||
import { ThirdwebProvider } from '@thirdweb-dev/react-native';
|
||||
|
||||
<ThirdwebProvider locale={'ja'}>
|
||||
<App />
|
||||
</ ThirdwebProvider>
|
||||
```
|
||||
|
||||
## 0.3.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</p>
|
||||
<p><strong>Powering react-native dapps.</strong></p>
|
||||
|
||||
The go to librarly for seamless Web3 integration in React Native apps.
|
||||
The go to library for seamless Web3 integration in React Native apps.
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.3.15",
|
||||
"version": "0.4.4",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,7 +31,6 @@
|
||||
"@magic-sdk/provider": "17.2.0",
|
||||
"@magic-sdk/react-native-bare": "^18.5.0",
|
||||
"@paperxyz/embedded-wallet-service-sdk": "^1.2.4",
|
||||
"@react-native-community/checkbox": "^0.5.16",
|
||||
"@shopify/restyle": "^2.4.2",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@thirdweb-dev/chains": "workspace:*",
|
||||
@@ -71,6 +70,7 @@
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-inclusive-language": "^2.2.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.16",
|
||||
"ethers": "^5.7.2",
|
||||
"expo": "^47.0.14",
|
||||
"jest": "^29.6.2",
|
||||
@@ -80,7 +80,7 @@
|
||||
"react-native-camera": "^4.2.1",
|
||||
"react-native-device-info": "10.6.0",
|
||||
"react-native-mmkv": "2.5.1",
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-safe-area-context": "4.7.4",
|
||||
"react-native-webview": "12.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typedoc": "^0.25.2",
|
||||
@@ -94,7 +94,7 @@
|
||||
"react-native-inappbrowser-reborn": "^3.7.0",
|
||||
"react-native-quick-base64": "^2.0.7",
|
||||
"react-native-quick-crypto": "^0.6.1",
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-safe-area-context": "4.7.4",
|
||||
"react-native-webview": "12.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -73,7 +73,7 @@ export class noopStorage implements IAsyncStorage {
|
||||
/**
|
||||
* Returns a new instance of AsyncLocalStorage
|
||||
*
|
||||
* @param name Name to namespace the storage with
|
||||
* @param name - Name to namespace the storage with
|
||||
* @returns A new instance of AsyncLocalStorage
|
||||
*/
|
||||
export function createAsyncLocalStorage(name: string) {
|
||||
@@ -83,7 +83,7 @@ export function createAsyncLocalStorage(name: string) {
|
||||
/**
|
||||
* Returns a new instance of LocalStorage
|
||||
*
|
||||
* @param name Name to namespace the storage with
|
||||
* @param name - Name to namespace the storage with
|
||||
* @returns A new instance of LocalStorage
|
||||
*/
|
||||
export function createSyncStorage(name: string) {
|
||||
|
||||
@@ -31,7 +31,7 @@ export class SecureStorage implements ISecureStorage {
|
||||
/**
|
||||
* Returns a new instance of SecureStorage implemented by Expo SecureStore
|
||||
*
|
||||
* @param name Name to namespace the storage with
|
||||
* @param name - Name to namespace the storage with
|
||||
* @returns A new instance of SecureStorage
|
||||
*/
|
||||
export function createSecureStorage(name: string) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import Svg, { Path } from "react-native-svg";
|
||||
import { IconStyleProp } from "./types";
|
||||
|
||||
const CheckedIcon = ({ width, height, color }: IconStyleProp) => {
|
||||
return (
|
||||
<Svg width={width} height={height} viewBox="0 0 15 15" fill="none">
|
||||
<Path
|
||||
d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z"
|
||||
fill={color}
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default CheckedIcon;
|
||||
@@ -1,3 +1,14 @@
|
||||
export const APPLE_ICON = `<svg fill="#959CA0" height="40px" width="40px" version="1.1" id="Capa_1" viewBox="0 0 24 24" xml:space="preserve" stroke="#959CA0"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M15.769,0c0.053,0,0.106,0,0.162,0c0.13,1.606-0.483,2.806-1.228,3.675c-0.731,0.863-1.732,1.7-3.351,1.573 c-0.108-1.583,0.506-2.694,1.25-3.561C13.292,0.879,14.557,0.16,15.769,0z"></path> <path d="M20.67,16.716c0,0.016,0,0.03,0,0.045c-0.455,1.378-1.104,2.559-1.896,3.655c-0.723,0.995-1.609,2.334-3.191,2.334 c-1.367,0-2.275-0.879-3.676-0.903c-1.482-0.024-2.297,0.735-3.652,0.926c-0.155,0-0.31,0-0.462,0 c-0.995-0.144-1.798-0.932-2.383-1.642c-1.725-2.098-3.058-4.808-3.306-8.276c0-0.34,0-0.679,0-1.019 c0.105-2.482,1.311-4.5,2.914-5.478c0.846-0.52,2.009-0.963,3.304-0.765c0.555,0.086,1.122,0.276,1.619,0.464 c0.471,0.181,1.06,0.502,1.618,0.485c0.378-0.011,0.754-0.208,1.135-0.347c1.116-0.403,2.21-0.865,3.652-0.648 c1.733,0.262,2.963,1.032,3.723,2.22c-1.466,0.933-2.625,2.339-2.427,4.74C17.818,14.688,19.086,15.964,20.67,16.716z"></path> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> </g> </g></svg>`;
|
||||
|
||||
export const FACEBOOK_ICON = `<svg xml:space="preserve" viewBox="0 0 40 40">
|
||||
<linearGradient id="a" x1="-277.375" x2="-277.375" y1="406.6018" y2="407.5726" gradientTransform="matrix(40 0 0 -39.7778 11115.001 16212.334)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#0062e0"/>
|
||||
<stop offset="1" stop-color="#19afff"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#a)" d="M16.7 39.8C7.2 38.1 0 29.9 0 20 0 9 9 0 20 0s20 9 20 20c0 9.9-7.2 18.1-16.7 19.8l-1.1-.9h-4.4l-1.1.9z"/>
|
||||
<path fill="#fff" d="m27.8 25.6.9-5.6h-5.3v-3.9c0-1.6.6-2.8 3-2.8H29V8.2c-1.4-.2-3-.4-4.4-.4-4.6 0-7.8 2.8-7.8 7.8V20h-5v5.6h5v14.1c1.1.2 2.2.3 3.3.3 1.1 0 2.2-.1 3.3-.3V25.6h4.4z"/>
|
||||
</svg>`;
|
||||
|
||||
export const GOOGLE_ICON = `<svg height={height} viewBox="0 0 24 24" width={width}>
|
||||
<path
|
||||
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
||||
|
||||
@@ -14,7 +14,11 @@ import { ConnectWalletButton } from "./ConnectWalletFlow/ConnectWalletButton";
|
||||
import { ConnectWalletButtonProps } from "./ConnectWalletFlow/ConnectWalletButton";
|
||||
import BaseButton from "./base/BaseButton";
|
||||
import Text from "./base/Text";
|
||||
import { useLocale, useUIContext } from "../providers/ui-context-provider";
|
||||
import {
|
||||
useGlobalTheme,
|
||||
useLocale,
|
||||
useUIContext,
|
||||
} from "../providers/ui-context-provider";
|
||||
import { ThemeProvider } from "../styles/ThemeProvider";
|
||||
import { SupportedTokens, defaultTokens } from "./SendFunds/defaultTokens";
|
||||
|
||||
@@ -32,7 +36,7 @@ export type ConnectWalletProps = {
|
||||
/**
|
||||
* Hide option to request testnet funds for testnets in dropdown
|
||||
*
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
hideTestnetFaucet?: boolean;
|
||||
|
||||
@@ -43,7 +47,7 @@ export type ConnectWalletProps = {
|
||||
* Please, note that if you support multiple networks in your app this prop should
|
||||
* be set to `false` to allow users to switch between networks.
|
||||
*
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
switchToActiveChain?: boolean;
|
||||
|
||||
@@ -65,6 +69,13 @@ export type ConnectWalletProps = {
|
||||
* ```
|
||||
*/
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
|
||||
/**
|
||||
* Hide the "switch to Personal wallet" option in the wallet modal which is shown when wallet is connected to a Smart Wallet
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
} & ConnectWalletButtonProps;
|
||||
|
||||
export const ConnectWallet = ({
|
||||
@@ -80,7 +91,9 @@ export const ConnectWallet = ({
|
||||
termsOfServiceUrl,
|
||||
privacyPolicyUrl,
|
||||
supportedTokens,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: ConnectWalletProps) => {
|
||||
const globalTheme = useGlobalTheme();
|
||||
const l = useLocale();
|
||||
const fadeAnim = useRef(new Animated.Value(0)).current;
|
||||
const address = useAddress();
|
||||
@@ -140,7 +153,10 @@ export const ConnectWallet = ({
|
||||
style={styles.connectWalletButton}
|
||||
>
|
||||
{switching ? (
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
<ActivityIndicator
|
||||
size="small"
|
||||
color={globalTheme.colors.buttonTextColor}
|
||||
/>
|
||||
) : (
|
||||
<Text variant="bodyLarge" color="buttonTextColor">
|
||||
{l.common.switch_network}
|
||||
@@ -155,6 +171,7 @@ export const ConnectWallet = ({
|
||||
hideTestnetFaucet={hideTestnetFaucet}
|
||||
supportedTokens={supportedTokensMemo}
|
||||
displayBalanceToken={displayBalanceToken}
|
||||
hideSwitchToPersonalWallet={hideSwitchToPersonalWallet}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useWallet } from "@thirdweb-dev/react-core";
|
||||
import { IWalletConnectReceiver } from "@thirdweb-dev/wallets";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import Box from "../base/Box";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
@@ -14,8 +13,13 @@ import WalletConnectIcon from "../../assets/wallet-connect";
|
||||
import QrCodeIcon from "../../assets/qr-code";
|
||||
import { QRCodeScan } from "./QRCodeScan";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
import { useWalletConnectHandler } from "../../providers/context-provider";
|
||||
|
||||
const ConnectAppField = () => {
|
||||
const ConnectAppField = ({
|
||||
onConnectAppTriggered,
|
||||
}: {
|
||||
onConnectAppTriggered?: () => void;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const l = useLocale();
|
||||
const [showWCInput, setShowWCInput] = useState(false);
|
||||
@@ -24,22 +28,19 @@ const ConnectAppField = () => {
|
||||
const wallet = useWallet();
|
||||
const [showQRCodeScan, setShowQRCodeScan] = useState(false);
|
||||
const wcUriRef = useRef<string | undefined>();
|
||||
const walletConnectHandler = useWalletConnectHandler();
|
||||
|
||||
const getAppMeta = useCallback(() => {
|
||||
if (wallet && "isWCReceiverEnabled" in wallet) {
|
||||
const sessions = (
|
||||
wallet as unknown as IWalletConnectReceiver
|
||||
).getActiveSessions();
|
||||
if (Object.keys(sessions).length > 0) {
|
||||
setAppMeta({
|
||||
name: sessions[0].peer.metadata.name,
|
||||
iconUrl: sessions[0].peer.metadata.icons[0],
|
||||
});
|
||||
}
|
||||
const sessions = walletConnectHandler?.getActiveSessions();
|
||||
if (sessions && Object.keys(sessions).length > 0) {
|
||||
setAppMeta({
|
||||
name: sessions[0].peer.metadata.name,
|
||||
iconUrl: sessions[0].peer.metadata.icons[0],
|
||||
});
|
||||
}
|
||||
}, [wallet]);
|
||||
}, [walletConnectHandler]);
|
||||
|
||||
const onSmartWalletWCMessage = useCallback(
|
||||
const onWalletConnectMessage = useCallback(
|
||||
({ type }: { type: string }) => {
|
||||
if (type === "session_approved") {
|
||||
getAppMeta();
|
||||
@@ -52,22 +53,22 @@ const ConnectAppField = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet) {
|
||||
wallet.addListener("message", onSmartWalletWCMessage);
|
||||
wallet.addListener("message", onWalletConnectMessage);
|
||||
|
||||
getAppMeta();
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (wallet) {
|
||||
wallet.removeListener("message", onSmartWalletWCMessage);
|
||||
wallet.removeListener("message", onWalletConnectMessage);
|
||||
}
|
||||
};
|
||||
}, [getAppMeta, onSmartWalletWCMessage, wallet]);
|
||||
}, [getAppMeta, onWalletConnectMessage, wallet]);
|
||||
|
||||
const onConnectDappPress = () => {
|
||||
if (appMeta) {
|
||||
reset();
|
||||
(wallet as unknown as IWalletConnectReceiver).disconnectSession();
|
||||
walletConnectHandler?.disconnectSession();
|
||||
} else {
|
||||
setShowWCInput(true);
|
||||
}
|
||||
@@ -84,9 +85,9 @@ const ConnectAppField = () => {
|
||||
|
||||
const onQRCodeScan = (data: string) => {
|
||||
if (wcUriRef.current !== data && data.startsWith("wc:")) {
|
||||
wcUriRef.current = data;
|
||||
setWCUri(data);
|
||||
setShowQRCodeScan(false);
|
||||
wcUriRef.current = data;
|
||||
|
||||
onWCPress(data);
|
||||
}
|
||||
@@ -103,10 +104,14 @@ const ConnectAppField = () => {
|
||||
|
||||
const uriToUse = uri || wcUri;
|
||||
|
||||
if (uriToUse?.startsWith("wc:")) {
|
||||
(wallet as unknown as IWalletConnectReceiver).connectApp(uriToUse);
|
||||
if (!uriToUse?.startsWith("wc:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
onConnectAppTriggered?.();
|
||||
|
||||
walletConnectHandler?.connectApp(uriToUse);
|
||||
|
||||
setWCUri(undefined);
|
||||
wcUriRef.current = undefined;
|
||||
};
|
||||
@@ -135,6 +140,7 @@ const ConnectAppField = () => {
|
||||
style: {
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
flex: 1,
|
||||
},
|
||||
}}
|
||||
containerProps={{
|
||||
|
||||
+16
-4
@@ -30,6 +30,8 @@ import { SupportedTokens } from "../SendFunds/defaultTokens";
|
||||
import { ActiveDot } from "../base";
|
||||
import { EmbeddedWallet } from "../../wallets/wallets/embedded/EmbeddedWallet";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
import { isWalletConnectReceiverEnabled } from "../../wallets/utils";
|
||||
import ConnectAppField from "./ConnectAppField";
|
||||
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
|
||||
const DEVICE_WIDTH = Dimensions.get("window").width;
|
||||
@@ -42,6 +44,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
hideTestnetFaucet,
|
||||
supportedTokens,
|
||||
displayBalanceToken,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: {
|
||||
isVisible: boolean;
|
||||
onClosePress: () => void;
|
||||
@@ -50,6 +53,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
hideTestnetFaucet?: boolean;
|
||||
supportedTokens: SupportedTokens;
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const [isExportModalVisible, setIsExportModalVisible] = useState(false);
|
||||
@@ -131,6 +135,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
return (
|
||||
<SmartWalletAdditionalActions
|
||||
onExportPress={onExportLocalWalletPress}
|
||||
hideSwitchToPersonalWallet={hideSwitchToPersonalWallet}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -203,11 +208,15 @@ export const ConnectWalletDetailsModal = ({
|
||||
return null;
|
||||
}, [
|
||||
activeWallet?.walletId,
|
||||
isImportModalVisible,
|
||||
onExportLocalWalletPress,
|
||||
onWalletImported,
|
||||
smartWallet,
|
||||
l,
|
||||
onExportLocalWalletPress,
|
||||
l.connect_wallet_details.additional_actions,
|
||||
l.connect_wallet_details.backup_wallet,
|
||||
l.connect_wallet_details.import_wallet,
|
||||
l.local_wallet.this_is_a_temporary_wallet,
|
||||
isImportModalVisible,
|
||||
onWalletImported,
|
||||
hideSwitchToPersonalWallet,
|
||||
]);
|
||||
|
||||
return (
|
||||
@@ -296,6 +305,9 @@ export const ConnectWalletDetailsModal = ({
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{isWalletConnectReceiverEnabled(activeWallet) ? (
|
||||
<ConnectAppField onConnectAppTriggered={onClosePress} />
|
||||
) : null}
|
||||
{getAdditionalActions()}
|
||||
{extraRows ? extraRows({}) : null}
|
||||
{addressCopied === true ? (
|
||||
|
||||
+7
-4
@@ -10,12 +10,15 @@ import { useState } from "react";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Box from "../base/Box";
|
||||
import { ModalHeaderTextClose } from "../base/modal/ModalHeaderTextClose";
|
||||
import { useAddress, useWallet } from "@thirdweb-dev/react-core";
|
||||
import {
|
||||
shortenAddress,
|
||||
useAddress,
|
||||
useWallet,
|
||||
} from "@thirdweb-dev/react-core";
|
||||
import { PasswordInput } from "../PasswordInput";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { SmartWallet } from "@thirdweb-dev/wallets";
|
||||
import { usePersonalWalletAddress } from "../../wallets/hooks/usePersonalWalletAddress";
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import { LocalWallet } from "../../wallets/wallets/LocalWallet";
|
||||
import { TWModal } from "../base/modal/TWModal";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
@@ -162,7 +165,7 @@ export const ExportLocalWalletModal = ({
|
||||
{l.local_wallet.wallet_address}
|
||||
</Text>
|
||||
<Text variant="bodySmallSecondary">
|
||||
{shortenWalletAddress(
|
||||
{shortenAddress(
|
||||
personalWalletAddress ? personalWalletAddress : address,
|
||||
)}
|
||||
</Text>
|
||||
@@ -180,7 +183,7 @@ export const ExportLocalWalletModal = ({
|
||||
onPress={onContinuePress}
|
||||
>
|
||||
{isExporting ? (
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
<ActivityIndicator size="small" color="black" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
{l.connect_wallet_details.backup}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { RNCamera } from "react-native-camera";
|
||||
import { TWModal } from "../base/modal/TWModal";
|
||||
import { ModalHeaderTextClose } from "../base/modal/ModalHeaderTextClose";
|
||||
import { SafeAreaView } from "react-native";
|
||||
|
||||
export const QRCodeScan = ({
|
||||
isVisible,
|
||||
@@ -13,21 +14,26 @@ export const QRCodeScan = ({
|
||||
}) => {
|
||||
return (
|
||||
<TWModal isVisible={isVisible} backdropOpacity={1}>
|
||||
<ModalHeaderTextClose headerText={"Scan to Connect"} onClose={onClose} />
|
||||
<RNCamera
|
||||
style={{ flex: 1 }}
|
||||
type={RNCamera.Constants.Type.back}
|
||||
captureAudio={false}
|
||||
androidCameraPermissionOptions={{
|
||||
title: "Permission to use camera",
|
||||
message: "We need your permission to use your camera",
|
||||
buttonPositive: "Ok",
|
||||
buttonNegative: "Cancel",
|
||||
}}
|
||||
onBarCodeRead={({ data }) => {
|
||||
onQRCodeScan(data);
|
||||
}}
|
||||
/>
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: "transparent" }}>
|
||||
<ModalHeaderTextClose
|
||||
headerText={"Scan to Connect"}
|
||||
onClose={onClose}
|
||||
/>
|
||||
<RNCamera
|
||||
style={{ flex: 1 }}
|
||||
type={RNCamera.Constants.Type.back}
|
||||
captureAudio={false}
|
||||
androidCameraPermissionOptions={{
|
||||
title: "Permission to use camera",
|
||||
message: "We need your permission to use your camera",
|
||||
buttonPositive: "Ok",
|
||||
buttonNegative: "Cancel",
|
||||
}}
|
||||
onBarCodeRead={({ data }) => {
|
||||
onQRCodeScan(data);
|
||||
}}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
</TWModal>
|
||||
);
|
||||
};
|
||||
|
||||
+4
-5
@@ -2,18 +2,19 @@ import { useWallet } from "@thirdweb-dev/react-core";
|
||||
import Box from "../base/Box";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Text from "../base/Text";
|
||||
import { IWalletConnectReceiver } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
CLOSE_MODAL_STATE,
|
||||
WalletConnectSessionProposalModal,
|
||||
} from "../../utils/modalTypes";
|
||||
import { useLocale, useModalState } from "../../providers/ui-context-provider";
|
||||
import { useWalletConnectHandler } from "../../providers/context-provider";
|
||||
|
||||
export const SessionProposalModal = () => {
|
||||
const l = useLocale();
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const { data: proposalData } =
|
||||
modalState as WalletConnectSessionProposalModal;
|
||||
const walletConnectHandler = useWalletConnectHandler();
|
||||
|
||||
const wallet = useWallet();
|
||||
|
||||
@@ -41,7 +42,7 @@ export const SessionProposalModal = () => {
|
||||
minWidth={100}
|
||||
borderColor="border"
|
||||
onPress={async () => {
|
||||
(wallet as unknown as IWalletConnectReceiver).rejectSession();
|
||||
walletConnectHandler?.rejectSession();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
@@ -61,9 +62,7 @@ export const SessionProposalModal = () => {
|
||||
if (!wallet) {
|
||||
throw new Error("Wallet not connected.");
|
||||
}
|
||||
await (
|
||||
wallet as unknown as IWalletConnectReceiver
|
||||
).approveSession();
|
||||
await walletConnectHandler?.approveSession();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
|
||||
+11
-15
@@ -1,19 +1,16 @@
|
||||
import { useChain, useWallet } from "@thirdweb-dev/react-core";
|
||||
import { shortenAddress, useChain, useWallet } from "@thirdweb-dev/react-core";
|
||||
import Box from "../base/Box";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Text from "../base/Text";
|
||||
import {
|
||||
EIP155_SIGNING_METHODS,
|
||||
IWalletConnectReceiver,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { EIP155_SIGNING_METHODS } from "@thirdweb-dev/wallets";
|
||||
import { useLocale, useModalState } from "../../providers/ui-context-provider";
|
||||
import {
|
||||
CLOSE_MODAL_STATE,
|
||||
WalletConnectSessionRequestModal,
|
||||
} from "../../utils/modalTypes";
|
||||
import { ActivityIndicator, Dimensions } from "react-native";
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useWalletConnectHandler } from "../../providers/context-provider";
|
||||
|
||||
const getTitle = (method: string) => {
|
||||
switch (method) {
|
||||
@@ -34,6 +31,7 @@ export const SessionRequestModal = () => {
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const { data: requestData } = modalState as WalletConnectSessionRequestModal;
|
||||
const [approvingRequest, setApprovingRequest] = useState(false);
|
||||
const walletConnectHandler = useWalletConnectHandler();
|
||||
|
||||
const wallet = useWallet();
|
||||
const chain = useChain();
|
||||
@@ -48,12 +46,10 @@ export const SessionRequestModal = () => {
|
||||
}
|
||||
|
||||
setApprovingRequest(true);
|
||||
(wallet as unknown as IWalletConnectReceiver)
|
||||
.approveRequest()
|
||||
.finally(() => {
|
||||
setApprovingRequest(false);
|
||||
onClose();
|
||||
});
|
||||
walletConnectHandler?.approveEIP155Request().finally(() => {
|
||||
setApprovingRequest(false);
|
||||
onClose();
|
||||
});
|
||||
};
|
||||
|
||||
const getContent = useCallback(() => {
|
||||
@@ -86,10 +82,10 @@ export const SessionRequestModal = () => {
|
||||
return (
|
||||
<Box>
|
||||
<Text variant="bodySmall" textAlign="left">
|
||||
{`${l.common.from}: ${shortenWalletAddress(from)}`}
|
||||
{`${l.common.from}: ${shortenAddress(from)}`}
|
||||
</Text>
|
||||
<Text variant="bodySmall" textAlign="left" mt="sm">
|
||||
{`${l.common.to}: ${shortenWalletAddress(to)}`}
|
||||
{`${l.common.to}: ${shortenAddress(to)}`}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
@@ -126,7 +122,7 @@ export const SessionRequestModal = () => {
|
||||
minWidth={100}
|
||||
borderColor="border"
|
||||
onPress={async () => {
|
||||
(wallet as unknown as IWalletConnectReceiver).rejectRequest();
|
||||
walletConnectHandler?.rejectEIP155Request();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
|
||||
+20
-20
@@ -11,15 +11,16 @@ import { useWalletContext, useWallet } from "@thirdweb-dev/react-core";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSmartWallet } from "../../providers/context-provider";
|
||||
import RightArrowIcon from "../../assets/right-arrow";
|
||||
import ConnectAppField from "./ConnectAppField";
|
||||
import DisconnectIcon from "../../assets/disconnect";
|
||||
import { IconTextButton } from "../base/IconTextButton";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export const SmartWalletAdditionalActions = ({
|
||||
onExportPress,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: {
|
||||
onExportPress: () => void;
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const { setConnectedWallet } = useWalletContext();
|
||||
@@ -61,25 +62,24 @@ export const SmartWalletAdditionalActions = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconTextButton
|
||||
mt="xs"
|
||||
text={
|
||||
showSmartWallet
|
||||
? l.smart_wallet.switch_to_smart
|
||||
: l.smart_wallet.switch_to_personal
|
||||
}
|
||||
icon={
|
||||
<DisconnectIcon
|
||||
width={14}
|
||||
height={14}
|
||||
color={theme.colors.iconPrimary}
|
||||
/>
|
||||
}
|
||||
onPress={onWalletPress}
|
||||
/>
|
||||
{!showSmartWallet && smartWallet?.enableConnectApp ? (
|
||||
<ConnectAppField />
|
||||
) : null}
|
||||
{(showSmartWallet || !hideSwitchToPersonalWallet) && (
|
||||
<IconTextButton
|
||||
mt="xs"
|
||||
text={
|
||||
showSmartWallet
|
||||
? l.smart_wallet.switch_to_smart
|
||||
: l.smart_wallet.switch_to_personal
|
||||
}
|
||||
icon={
|
||||
<DisconnectIcon
|
||||
width={14}
|
||||
height={14}
|
||||
color={theme.colors.iconPrimary}
|
||||
/>
|
||||
}
|
||||
onPress={onWalletPress}
|
||||
/>
|
||||
)}
|
||||
{wallet?.walletId === walletIds.localWallet ||
|
||||
activeWallet?.walletId === walletIds.localWallet ? (
|
||||
<>
|
||||
|
||||
+10
-8
@@ -10,7 +10,7 @@ import { useMemo, useState } from "react";
|
||||
import { TextBalance } from "../base/TextBalance";
|
||||
import { SupportedTokens } from "../SendFunds/defaultTokens";
|
||||
import { SMART_WALLET_ICON } from "../../assets/svgs";
|
||||
import { ImageSvgUri } from "../base";
|
||||
import { WalletIcon } from "../base";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export type ConnectWalletDetailsProps = {
|
||||
@@ -36,6 +36,12 @@ export type ConnectWalletDetailsProps = {
|
||||
* ```
|
||||
*/
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
/**
|
||||
* Hide the "switch to Personal wallet" option in the dropdown which is shown when wallet is connected to a Smart Wallet
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
};
|
||||
|
||||
export const WalletDetailsButton = ({
|
||||
@@ -45,6 +51,7 @@ export const WalletDetailsButton = ({
|
||||
hideTestnetFaucet,
|
||||
supportedTokens,
|
||||
displayBalanceToken,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: ConnectWalletDetailsProps) => {
|
||||
const l = useLocale();
|
||||
const activeWallet = useWallet();
|
||||
@@ -76,6 +83,7 @@ export const WalletDetailsButton = ({
|
||||
hideTestnetFaucet={hideTestnetFaucet}
|
||||
supportedTokens={supportedTokens}
|
||||
displayBalanceToken={displayBalanceToken}
|
||||
hideSwitchToPersonalWallet={hideSwitchToPersonalWallet}
|
||||
/>
|
||||
{detailsButton ? (
|
||||
detailsButton({ onPress })
|
||||
@@ -92,13 +100,7 @@ export const WalletDetailsButton = ({
|
||||
alignContent="center"
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
<Box borderRadius="lg" overflow="hidden">
|
||||
<ImageSvgUri
|
||||
width={32}
|
||||
height={32}
|
||||
imageUrl={avatarUrl || walletIconUrl}
|
||||
/>
|
||||
</Box>
|
||||
<WalletIcon iconUri={avatarUrl || walletIconUrl} size={32} />
|
||||
<Box ml="md" justifyContent="center" alignItems="flex-start">
|
||||
{activeWallet?.walletId === LocalWallet.id ? (
|
||||
<Text variant="bodySmall" color="red">
|
||||
|
||||
+22
-26
@@ -104,35 +104,31 @@ export function ChooseWallet({
|
||||
onBackPress={isConnectAWalletEnabled ? onBackPress : undefined}
|
||||
onClose={onClose}
|
||||
headerText={
|
||||
headerText ? (
|
||||
headerText
|
||||
) : (
|
||||
<Box
|
||||
flexDirection="row"
|
||||
alignItems="center"
|
||||
alignContent="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
{modalTitleIconUrl !== undefined ? (
|
||||
modalTitleIconUrl.length === 0 ? null : (
|
||||
<ImageSvgUri
|
||||
width={26}
|
||||
height={15}
|
||||
imageUrl={modalTitleIconUrl}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<ThirdwebLogo
|
||||
<Box
|
||||
flexDirection="row"
|
||||
alignItems="center"
|
||||
alignContent="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
{modalTitleIconUrl !== undefined ? (
|
||||
modalTitleIconUrl.length === 0 ? null : (
|
||||
<ImageSvgUri
|
||||
width={26}
|
||||
height={15}
|
||||
color={theme.colors.backgroundInverted}
|
||||
imageUrl={modalTitleIconUrl}
|
||||
/>
|
||||
)}
|
||||
<Text variant="headerBold" ml="xxs" fontSize={20} lineHeight={24}>
|
||||
{l.connect_wallet_details.connect}
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<ThirdwebLogo
|
||||
width={26}
|
||||
height={15}
|
||||
color={theme.colors.backgroundInverted}
|
||||
/>
|
||||
)}
|
||||
<Text variant="headerBold" ml="xxs" fontSize={20} lineHeight={24}>
|
||||
{headerText ? headerText : l.connect_wallet_details.connect}
|
||||
</Text>
|
||||
</Box>
|
||||
}
|
||||
subHeaderText={subHeaderText}
|
||||
/>
|
||||
|
||||
@@ -13,12 +13,12 @@ export type ConnectWalletButtonProps = {
|
||||
theme?: ThemeProviderProps["theme"];
|
||||
/**
|
||||
* Set a custom title for the button
|
||||
* @default "Connect Wallet"
|
||||
* @defaultValue "Connect Wallet"
|
||||
*/
|
||||
buttonTitle?: string;
|
||||
/**
|
||||
* Set a custom title for the Connect Wallet modal
|
||||
* @default "Choose your wallet"
|
||||
* @defaultValue "Choose your wallet"
|
||||
*/
|
||||
modalTitle?: string;
|
||||
/**
|
||||
@@ -104,7 +104,10 @@ export const ConnectWalletButton = ({
|
||||
>
|
||||
<Text variant="bodyLargeBold" color="buttonTextColor">
|
||||
{showButtonSpinner ? (
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
<ActivityIndicator
|
||||
size="small"
|
||||
color={appTheme.colors.buttonTextColor}
|
||||
/>
|
||||
) : buttonTitle ? (
|
||||
buttonTitle
|
||||
) : (
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ export const ConnectWalletHeader = ({
|
||||
</Text>
|
||||
) : null}
|
||||
{subHeaderText ? (
|
||||
<Text variant="subHeader" mt="md">
|
||||
<Text variant="subHeader" mt="md" textAlign="center">
|
||||
{subHeaderText}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
@@ -74,7 +74,7 @@ export function LocalWalletFlow({
|
||||
data-test="create-new-wallet-button"
|
||||
>
|
||||
{isCreatingWallet ? (
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
<ActivityIndicator size="small" color="black" />
|
||||
) : (
|
||||
<Text variant="bodyLarge" color="black">
|
||||
{l.local_wallet.create_new_wallet}
|
||||
|
||||
+1
-1
@@ -228,7 +228,7 @@ export const LocalWalletImportModal = ({
|
||||
onPress={onImportPress}
|
||||
>
|
||||
{isImporting ? (
|
||||
<ActivityIndicator size="small" color="buttonTextColor" />
|
||||
<ActivityIndicator size="small" color="black" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
{l.common.import}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { SessionRequestModal } from "./ConnectWalletDetails/SessionRequestModal"
|
||||
import { SessionProposalModal } from "./ConnectWalletDetails/SessionProposalModal";
|
||||
import { TWModal } from "./base/modal/TWModal";
|
||||
import Box from "./base/Box";
|
||||
// import { useAppTheme } from "../styles/hooks";
|
||||
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
|
||||
const DEVICE_WIDTH = Dimensions.get("window").width;
|
||||
@@ -25,8 +24,6 @@ export const MainModal = () => {
|
||||
switch (modalState?.view) {
|
||||
case "ConnectWalletFlow":
|
||||
return <ConnectWalletFlow />;
|
||||
// case "WalletDetails":
|
||||
// return <ConnectWalletDetailsModal />;
|
||||
case "WalletConnectSessionRequestModal":
|
||||
return <SessionRequestModal />;
|
||||
case "WalletConnectSessionProposalModal":
|
||||
|
||||
@@ -18,7 +18,7 @@ import type { CallOverrides, ContractInterface } from "ethers";
|
||||
import { PropsWithChildren, useEffect } from "react";
|
||||
import { ActivityIndicator, StyleSheet } from "react-native";
|
||||
import invariant from "tiny-invariant";
|
||||
import { useUIContext } from "../providers/ui-context-provider";
|
||||
import { useGlobalTheme, useUIContext } from "../providers/ui-context-provider";
|
||||
|
||||
type ActionFn = (contract: SmartContract) => Promise<any>;
|
||||
|
||||
@@ -74,6 +74,7 @@ export const Web3Button = <TAction extends ActionFn>({
|
||||
theme,
|
||||
connectWalletProps,
|
||||
}: PropsWithChildren<Web3ButtonProps<TAction>>) => {
|
||||
const globalTheme = useGlobalTheme();
|
||||
const address = useAddress();
|
||||
const activeWallet = useWallet();
|
||||
const walletChainId = useChainId();
|
||||
@@ -155,7 +156,12 @@ export const Web3Button = <TAction extends ActionFn>({
|
||||
connectionStatus === "connecting" ||
|
||||
connectionStatus === "unknown"
|
||||
) {
|
||||
content = <ActivityIndicator size="small" color="buttonTextColor" />;
|
||||
content = (
|
||||
<ActivityIndicator
|
||||
size="small"
|
||||
color={globalTheme.colors.buttonTextColor}
|
||||
/>
|
||||
);
|
||||
buttonLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { shortenAddress } from "@thirdweb-dev/react-core";
|
||||
import { Theme } from "../../styles/theme";
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import Text from "./Text";
|
||||
|
||||
type AddressProps = {
|
||||
@@ -16,7 +16,7 @@ export const AddressDisplay = ({
|
||||
}: AddressProps) => {
|
||||
return (
|
||||
<Text variant={variant} {...props}>
|
||||
{shortenWalletAddress(address, extraShort)}
|
||||
{shortenAddress(address, extraShort)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import React, { useRef, useEffect } from "react";
|
||||
import { Animated, ViewProps } from "react-native";
|
||||
|
||||
interface BouncingContainerProps extends ViewProps {
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
const BouncingContainer: React.FC<BouncingContainerProps> = ({
|
||||
children,
|
||||
duration = 500,
|
||||
...props
|
||||
}) => {
|
||||
const bounceValue = useRef(new Animated.Value(0)).current;
|
||||
|
||||
useEffect(() => {
|
||||
Animated.loop(
|
||||
Animated.sequence([
|
||||
Animated.timing(bounceValue, {
|
||||
toValue: 10,
|
||||
duration,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(bounceValue, {
|
||||
toValue: 0,
|
||||
duration,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
).start();
|
||||
}, [bounceValue, duration]);
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
{...props}
|
||||
style={[
|
||||
props.style,
|
||||
{
|
||||
transform: [{ translateY: bounceValue }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
export default BouncingContainer;
|
||||
@@ -0,0 +1,43 @@
|
||||
import React, { useState } from "react";
|
||||
import Text from "./Text";
|
||||
import CheckedIcon from "../../assets/checked-icon";
|
||||
import BaseButton from "./BaseButton";
|
||||
import Box from "./Box";
|
||||
|
||||
interface CheckboxProps {
|
||||
label: string;
|
||||
color: string;
|
||||
value?: boolean;
|
||||
onToggle?: (value: boolean) => void;
|
||||
}
|
||||
|
||||
const Checkbox: React.FC<CheckboxProps> = ({
|
||||
label,
|
||||
color,
|
||||
onToggle,
|
||||
value = false,
|
||||
}) => {
|
||||
const [isChecked, setIsChecked] = useState(value);
|
||||
|
||||
const onPress = () => {
|
||||
setIsChecked(!isChecked);
|
||||
onToggle?.(!isChecked);
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseButton flexDirection="row" alignItems="center" onPress={onPress}>
|
||||
<Box borderRadius="md" style={{ borderColor: color }} borderWidth={1}>
|
||||
{isChecked ? (
|
||||
<CheckedIcon width={20} height={20} color={color} />
|
||||
) : (
|
||||
<Box width={20} height={20} />
|
||||
)}
|
||||
</Box>
|
||||
<Text variant="bodySmall" ml="xxs">
|
||||
{label}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default Checkbox;
|
||||
@@ -0,0 +1,48 @@
|
||||
import BaseButton from "./BaseButton";
|
||||
import Box from "./Box";
|
||||
import ImageSvgUri from "./ImageSvgUri";
|
||||
import Text from "./Text";
|
||||
|
||||
type SquareButtonProps = {
|
||||
onPress: () => void;
|
||||
iconUrl: string;
|
||||
size: number;
|
||||
name?: string;
|
||||
} & (typeof BaseButton)["arguments"];
|
||||
|
||||
export const SquareButton = ({
|
||||
onPress,
|
||||
iconUrl,
|
||||
name,
|
||||
size,
|
||||
...props
|
||||
}: SquareButtonProps) => {
|
||||
return (
|
||||
<BaseButton
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
borderWidth={0}
|
||||
borderRadius="sm"
|
||||
width={size}
|
||||
height={size}
|
||||
onPress={onPress}
|
||||
{...props}
|
||||
>
|
||||
<Box borderWidth={0} borderRadius="lg">
|
||||
<ImageSvgUri imageUrl={iconUrl} width={size} height={size} />
|
||||
</Box>
|
||||
{name ? (
|
||||
<Text
|
||||
variant="bodySmallSecondary"
|
||||
numberOfLines={1}
|
||||
mt="xs"
|
||||
fontSize={14}
|
||||
lineHeight={16}
|
||||
>
|
||||
{name}
|
||||
</Text>
|
||||
) : null}
|
||||
</BaseButton>
|
||||
);
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
import { useGlobalTheme } from "../../providers/ui-context-provider";
|
||||
import BaseButton from "./BaseButton";
|
||||
import Box from "./Box";
|
||||
import ImageSvgUri from "./ImageSvgUri";
|
||||
import Text from "./Text";
|
||||
|
||||
type WalletButtonSquareProps = {
|
||||
onPress: () => void;
|
||||
walletIconUrl: string;
|
||||
size: number;
|
||||
name: string;
|
||||
} & (typeof BaseButton)["arguments"];
|
||||
|
||||
export const WalletButtonSquare = ({
|
||||
onPress,
|
||||
walletIconUrl,
|
||||
name,
|
||||
size,
|
||||
}: WalletButtonSquareProps) => {
|
||||
const theme = useGlobalTheme();
|
||||
|
||||
const marginVertical = theme.spacing.xs;
|
||||
return (
|
||||
<BaseButton
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
marginVertical="xxs"
|
||||
borderWidth={0}
|
||||
borderRadius="sm"
|
||||
width={size - marginVertical * 2}
|
||||
height={size - marginVertical * 2}
|
||||
onPress={onPress}
|
||||
>
|
||||
<Box borderWidth={0} borderRadius="lg">
|
||||
<ImageSvgUri
|
||||
imageUrl={walletIconUrl}
|
||||
width={size * 0.6}
|
||||
height={size * 0.6}
|
||||
/>
|
||||
</Box>
|
||||
<Text
|
||||
variant="bodySmallSecondary"
|
||||
numberOfLines={1}
|
||||
mt="xs"
|
||||
fontSize={14}
|
||||
lineHeight={16}
|
||||
>
|
||||
{name}
|
||||
</Text>
|
||||
</BaseButton>
|
||||
);
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import Box from "./Box";
|
||||
import ImageSvgUri from "./ImageSvgUri";
|
||||
|
||||
export const WalletIcon = ({
|
||||
@@ -7,5 +8,9 @@ export const WalletIcon = ({
|
||||
iconUri: string;
|
||||
size: number;
|
||||
}) => {
|
||||
return <ImageSvgUri imageUrl={iconUri} width={size} height={size} />;
|
||||
return (
|
||||
<Box borderRadius="sm" overflow="hidden">
|
||||
<ImageSvgUri imageUrl={iconUri} width={size} height={size} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
export const _en = {
|
||||
connect_wallet: {
|
||||
label: "Connect Wallet",
|
||||
},
|
||||
connect_wallet_details: {
|
||||
additional_actions: "Additional Actions",
|
||||
address_copied_clipboard: "Address copied to clipboard",
|
||||
backup_wallet: "Backup Wallet",
|
||||
backup_personal_wallet: "Backup personal wallet",
|
||||
import_wallet: "Import Wallet",
|
||||
connected_to_smart_wallet: "Connected to a Smart Wallet",
|
||||
current_network: "Current Network",
|
||||
backup: "Backup",
|
||||
connect_to_app: "Connect to App",
|
||||
guest: "Guest",
|
||||
connect: "Connect",
|
||||
new_to_wallets: "New to wallets?",
|
||||
view_transaction_history: "View Transaction History",
|
||||
get_started: "Get started",
|
||||
receive_funds: "Receive Funds",
|
||||
search_or_paste_token: "Search or paste token address",
|
||||
connect_a_wallet: "Connect a wallet",
|
||||
continue_as_guest: "Continue as guest",
|
||||
tos: "Terms of Service",
|
||||
privacy_policy: "Privacy Policy",
|
||||
by_connecting_you_agree: "By connecting, you agree to the",
|
||||
copy_address_or_scan:
|
||||
"Copy the wallet address or scan the QR code to send funds to this wallet.",
|
||||
request_testnet_funds: "Request Testnet Funds",
|
||||
your_address: "Your address",
|
||||
qr_code: "QR Code",
|
||||
select_token: "Select Token",
|
||||
send_to: "Send to",
|
||||
send_funds: "Send Funds",
|
||||
no_tokens_found: "No Tokens found",
|
||||
confirm_in_wallet: "Confirm in your wallet",
|
||||
select_network: "Select Network",
|
||||
switch_to: "Switch to",
|
||||
no_supported_chains_detected: "No supported chains detected",
|
||||
recommended: "Recommended",
|
||||
network_mismatch:
|
||||
"There's a network mismatch between your contract and your wallet",
|
||||
},
|
||||
connecting_wallet: {
|
||||
creating_encrypting:
|
||||
"Creating, encrypting and securing your device wallet.",
|
||||
connecting_your_wallet: "Connecting your wallet",
|
||||
connecting_through_pop_up:
|
||||
"Login and connect your app through the wallet pop-up",
|
||||
},
|
||||
local_wallet: {
|
||||
guest_wallet: "Guest Wallet",
|
||||
backup_your_wallet: "Backup your wallet",
|
||||
create_new_wallet: "Create new wallet",
|
||||
private_key_mnemonic: "Or Private key or Mnemonic",
|
||||
private_key_mnemonic_placeholder: "Private key / Mnemonic",
|
||||
application_can_authorize_transactions:
|
||||
"The application can authorize any transactions on behalf of the wallet without any approvals. We recommend only connecting to trusted applications.",
|
||||
double_check_password: "Please, double check your password or private key.",
|
||||
error_accessing_file: "Error accessing the file. Please try again.",
|
||||
wallet_address: "Wallet Address",
|
||||
this_will_download_json:
|
||||
"This will download a JSON file containing your wallet information onto your device encrypted with the password.",
|
||||
this_is_a_temporary_wallet:
|
||||
"This is a temporary guest wallet. Download a backup if you don't want to loose access to it.",
|
||||
},
|
||||
smart_wallet: {
|
||||
switch_to_smart: "Switch to Smart Wallet",
|
||||
switch_to_personal: "Switch to Personal Wallet",
|
||||
network_mismatch: "Network Mismatch",
|
||||
connecting: "Connecting",
|
||||
},
|
||||
embedded_wallet: {
|
||||
request_new_code: "Request new code",
|
||||
sign_in: "Sign In",
|
||||
sign_in_google: "Sign in with Google",
|
||||
sign_in_facebook: "Sign in with Facebook",
|
||||
sign_in_apple: "Sign in with Apple",
|
||||
sign_in_email: "Sign in with Email",
|
||||
enter_your_email: "Enter your email address",
|
||||
forgot_password: "Forgot password",
|
||||
enter_account_recovery_code: "Enter account recovery code",
|
||||
backup_your_account: "Backup your account",
|
||||
create_password: "Create password",
|
||||
enter_password: "Enter password",
|
||||
set_password_message: "Set a password to secure your account",
|
||||
enter_password_for_email: "Enter password for",
|
||||
make_sure_you_save_it: "Make sure you save it",
|
||||
},
|
||||
wallet_connect: {
|
||||
no_results_found: "No results found",
|
||||
search_wallets: "Search Wallets",
|
||||
},
|
||||
common: {
|
||||
connect_app: "Connect app",
|
||||
unknown_network: "Unknown Network",
|
||||
fetching: "Fetching...",
|
||||
password: "Password",
|
||||
reject: "Reject",
|
||||
approve: "Approve",
|
||||
switch_network: "Switch Network",
|
||||
import: "Import",
|
||||
username: "Username",
|
||||
amount: "Amount",
|
||||
send: "Send",
|
||||
receive: "Receive",
|
||||
continue: "Continue",
|
||||
error_switching_network: "Error switching network",
|
||||
or: "OR",
|
||||
from: "from",
|
||||
to: "from",
|
||||
next: "Next",
|
||||
learn_more: "Learn More",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
export const _es = {
|
||||
connect_wallet: {
|
||||
label: "Conectar Cartera",
|
||||
},
|
||||
connect_wallet_details: {
|
||||
additional_actions: "Acciones Adicionales",
|
||||
address_copied_clipboard: "Dirección copiada al portapapeles",
|
||||
backup_wallet: "Respaldar Cartera",
|
||||
backup_personal_wallet: "Respaldar cartera personal",
|
||||
import_wallet: "Importar Cartera",
|
||||
connected_to_smart_wallet: "Conectado a una Cartera Inteligente",
|
||||
current_network: "Red Actual",
|
||||
backup: "Respaldar",
|
||||
connect_to_app: "Conectar a la Aplicación",
|
||||
guest: "Invitado",
|
||||
connect: "Conectar",
|
||||
new_to_wallets: "¿Nuevo en carteras?",
|
||||
view_transaction_history: "Ver Historial de Transacciones",
|
||||
get_started: "Comenzar",
|
||||
receive_funds: "Recibir Fondos",
|
||||
search_or_paste_token: "Buscar o pegar dirección del token",
|
||||
connect_a_wallet: "Conectar una cartera",
|
||||
continue_as_guest: "Continuar como invitado",
|
||||
tos: "Términos de Servicio",
|
||||
privacy_policy: "Política de Privacidad",
|
||||
by_connecting_you_agree: "Al conectar, aceptas los",
|
||||
copy_address_or_scan:
|
||||
"Copia la dirección de la cartera o escanea el código QR para enviar fondos a esta cartera.",
|
||||
request_testnet_funds: "Solicitar Fondos de Testnet",
|
||||
your_address: "Tu dirección",
|
||||
qr_code: "Código QR",
|
||||
select_token: "Seleccionar Token",
|
||||
send_to: "Enviar a",
|
||||
send_funds: "Enviar Fondos",
|
||||
no_tokens_found: "No se encontraron tokens",
|
||||
confirm_in_wallet: "Confirma en tu cartera",
|
||||
select_network: "Seleccionar Red",
|
||||
switch_to: "Cambiar a",
|
||||
no_supported_chains_detected: "No se detectaron cadenas compatibles",
|
||||
recommended: "Recomendado",
|
||||
network_mismatch: "Hay un desajuste de red entre tu contrato y tu cartera",
|
||||
},
|
||||
connecting_wallet: {
|
||||
creating_encrypting:
|
||||
"Creando, cifrando y asegurando tu cartera de dispositivo.",
|
||||
connecting_your_wallet: "Conectando tu cartera",
|
||||
connecting_through_pop_up:
|
||||
"Iniciar sesión y conectar tu aplicación a través del pop-up de la cartera",
|
||||
},
|
||||
local_wallet: {
|
||||
guest_wallet: "Cartera de Invitado",
|
||||
backup_your_wallet: "Haz un respaldo de tu cartera",
|
||||
create_new_wallet: "Crear nueva cartera",
|
||||
private_key_mnemonic: "O clave privada o frase mnemotécnica",
|
||||
private_key_mnemonic_placeholder: "Clave privada / Frase mnemotécnica",
|
||||
application_can_authorize_transactions:
|
||||
"La aplicación puede autorizar cualquier transacción en nombre de la cartera sin aprobaciones. Recomendamos conectar solo a aplicaciones de confianza.",
|
||||
double_check_password: "Por favor, verifica tu contraseña o clave privada.",
|
||||
error_accessing_file:
|
||||
"Error al acceder al archivo. Por favor, inténtalo de nuevo.",
|
||||
wallet_address: "Dirección de la Cartera",
|
||||
this_will_download_json:
|
||||
"Esto descargará un archivo JSON que contiene la información de tu cartera en tu dispositivo cifrada con la contraseña.",
|
||||
this_is_a_temporary_wallet:
|
||||
"Esta es una cartera de invitado temporal. Descarga un respaldo si no quieres perder el acceso a ella.",
|
||||
},
|
||||
smart_wallet: {
|
||||
switch_to_smart: "Cambiar a Cartera Inteligente",
|
||||
switch_to_personal: "Cambiar a Cartera Personal",
|
||||
network_mismatch: "Desajuste de Red",
|
||||
connecting: "Conectando",
|
||||
},
|
||||
embedded_wallet: {
|
||||
request_new_code: "Solicitar nuevo código",
|
||||
sign_in: "Iniciar Sesión",
|
||||
sign_in_google: "Iniciar sesión con Google",
|
||||
sign_in_facebook: "Iniciar sesión con Facebook",
|
||||
sign_in_apple: "Iniciar sesión con Apple",
|
||||
sign_in_email: "Iniciar sesión con Email",
|
||||
enter_your_email: "Ingresa tu dirección de correo electrónico",
|
||||
forgot_password: "Olvidé mi contraseña",
|
||||
enter_account_recovery_code: "Ingresa el código de recuperación de cuenta",
|
||||
backup_your_account: "Haz un respaldo de tu cuenta",
|
||||
enter_password: "Introduce contraseña",
|
||||
create_password: "Crear contraseña",
|
||||
set_password_message:
|
||||
"Establece una contraseña para tu cuenta. Necesitarás esta contraseña cuando te conectes desde un nuevo dispositivo.",
|
||||
enter_password_for_email: "Ingresa la contraseña del correo electrónico",
|
||||
make_sure_you_save_it: "Asegúrate de guardarlo",
|
||||
},
|
||||
wallet_connect: {
|
||||
no_results_found: "No se encontraron resultados",
|
||||
search_wallets: "Buscar Carteras",
|
||||
},
|
||||
common: {
|
||||
connect_app: "Conectar aplicación",
|
||||
unknown_network: "Red Desconocida",
|
||||
fetching: "Recuperando...",
|
||||
password: "Contraseña",
|
||||
reject: "Rechazar",
|
||||
approve: "Aprobar",
|
||||
switch_network: "Cambiar Red",
|
||||
import: "Importar",
|
||||
username: "Nombre de usuario",
|
||||
amount: "Cantidad",
|
||||
send: "Enviar",
|
||||
receive: "Recibir",
|
||||
continue: "Continuar",
|
||||
error_switching_network: "Error al cambiar de red",
|
||||
or: "O",
|
||||
from: "de",
|
||||
to: "a",
|
||||
next: "Siguiente",
|
||||
learn_more: "Saber más",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
export const _ja = {
|
||||
connect_wallet: {
|
||||
label: "ウォレットを接続",
|
||||
},
|
||||
connect_wallet_details: {
|
||||
additional_actions: "追加のアクション",
|
||||
address_copied_clipboard: "アドレスがクリップボードにコピーされました。",
|
||||
backup_wallet: "ウォレットのバックアップ",
|
||||
backup_personal_wallet: "個人のウォレットのバックアップ",
|
||||
import_wallet: "ウォレットのインポート",
|
||||
connected_to_smart_wallet: "スマートウォレットに接続されています。",
|
||||
current_network: "現在のネットワーク",
|
||||
backup: "バックアップ",
|
||||
connect_to_app: "アプリに接続",
|
||||
guest: "ゲスト",
|
||||
connect: "接続",
|
||||
new_to_wallets: "ウォレットは初めてですか?",
|
||||
view_transaction_history: "取引履歴を見る",
|
||||
get_started: "開始する",
|
||||
receive_funds: "資金を受け取る",
|
||||
search_or_paste_token: "トークンのアドレスを検索または貼り付け",
|
||||
connect_a_wallet: "ウォレットを接続",
|
||||
continue_as_guest: "ゲストとして続行",
|
||||
tos: "利用規約",
|
||||
privacy_policy: "プライバシーポリシー",
|
||||
by_connecting_you_agree: "同意の上、接続してください。",
|
||||
copy_address_or_scan:
|
||||
"ウォレットのアドレスをコピーするか、QRコードをスキャンして資金をこのウォレットに送信します。",
|
||||
request_testnet_funds: "テストネットの資金をリクエスト",
|
||||
your_address: "あなたのアドレス",
|
||||
qr_code: "QRコード",
|
||||
select_token: "トークンを選択",
|
||||
send_to: "送信先",
|
||||
send_funds: "資金を送る",
|
||||
no_tokens_found: "トークンが見つかりません。",
|
||||
confirm_in_wallet: "ウォレットで確認",
|
||||
select_network: "ネットワークを選択",
|
||||
switch_to: "切り替え先",
|
||||
no_supported_chains_detected:
|
||||
"サポートされているチェーンが検出されませんでした。",
|
||||
recommended: "推奨",
|
||||
network_mismatch:
|
||||
"あなたのコントラクトとウォレットの間にネットワークの不一致があります。",
|
||||
},
|
||||
connecting_wallet: {
|
||||
creating_encrypting: "デバイスのウォレットを作成、暗号化、保護しています。",
|
||||
connecting_your_wallet: "ウォレットを接続しています。",
|
||||
connecting_through_pop_up:
|
||||
"ウォレットのポップアップを通じてアプリにログインして接続します。",
|
||||
},
|
||||
local_wallet: {
|
||||
guest_wallet: "ゲストウォレット",
|
||||
backup_your_wallet: "ウォレットをバックアップ",
|
||||
create_new_wallet: "新しいウォレットを作成",
|
||||
private_key_mnemonic: "または、秘密鍵またはニーモニック",
|
||||
private_key_mnemonic_placeholder: "秘密鍵 / ニーモニック",
|
||||
application_can_authorize_transactions:
|
||||
"アプリケーションは、承認なしにウォレットを代わりにトランザクションを許可することができます。信頼できるアプリケーションのみに接続することをおすすめします。",
|
||||
double_check_password: "パスワードまたは秘密鍵を再度確認してください。",
|
||||
error_accessing_file:
|
||||
"ファイルにアクセスできませんでしたもう一度試してください。",
|
||||
wallet_address: "ウォレットのアドレス",
|
||||
this_will_download_json:
|
||||
"これにより、パスワードで暗号化されたウォレット情報を含むJSONファイルがデバイスにダウンロードされます。",
|
||||
this_is_a_temporary_wallet:
|
||||
"これは一時的なゲストウォレットです。アクセスを失わないようにバックアップをダウンロードしてください。",
|
||||
},
|
||||
smart_wallet: {
|
||||
switch_to_smart: "スマートウォレットに切り替え",
|
||||
switch_to_personal: "個人のウォレットに切り替え",
|
||||
network_mismatch: "ネットワークの不一致",
|
||||
connecting: "接続中",
|
||||
},
|
||||
embedded_wallet: {
|
||||
request_new_code: "新しいコードをリクエスト",
|
||||
sign_in: "サインイン",
|
||||
sign_in_google: "Googleでサインイン",
|
||||
sign_in_facebook: "Facebookでサインイン",
|
||||
sign_in_apple: "Appleでサインイン",
|
||||
sign_in_email: "メールアドレスでサインイン",
|
||||
enter_your_email: "メールアドレスを入力",
|
||||
forgot_password: "パスワードを忘れた場合",
|
||||
enter_account_recovery_code: "アカウント回復コードを入力",
|
||||
backup_your_account: "アカウントのバックアップ",
|
||||
create_password: "パスワードを作成",
|
||||
enter_password: "パスワードを入力",
|
||||
set_password_message: "パスワードを設定してアカウントを保護",
|
||||
enter_password_for_email: "メールアドレスに対するパスワードを入力",
|
||||
make_sure_you_save_it: "必ず保存してください。",
|
||||
},
|
||||
wallet_connect: {
|
||||
no_results_found: "結果が見つかりません。",
|
||||
search_wallets: "ウォレットを検索",
|
||||
},
|
||||
common: {
|
||||
connect_app: "アプリに接続",
|
||||
unknown_network: "不明なネットワーク",
|
||||
fetching: "取得中...",
|
||||
password: "パスワード",
|
||||
reject: "拒否",
|
||||
approve: "承認",
|
||||
switch_network: "ネットワークの切り替え",
|
||||
import: "インポート",
|
||||
username: "ユーザー名",
|
||||
amount: "金額",
|
||||
send: "送信",
|
||||
receive: "受け取り",
|
||||
continue: "続行",
|
||||
error_switching_network: "ネットワークの切り替えエラー",
|
||||
or: "または",
|
||||
from: "から",
|
||||
to: "まで",
|
||||
next: "次へ",
|
||||
learn_more: "もっと詳しく",
|
||||
},
|
||||
};
|
||||
@@ -1,13 +1,21 @@
|
||||
import { DeepPartial, deepMerge } from "../types/deepPartial";
|
||||
import { Locale, LocaleType, _en } from "./types";
|
||||
import { _en } from "./en";
|
||||
import { _es } from "./es";
|
||||
import { _ja } from "./ja";
|
||||
import { Locale, LocaleType } from "./types";
|
||||
|
||||
export const setLocale = (locale: Locale): LocaleType => {
|
||||
if (typeof locale === "string") {
|
||||
if (locale === "en") {
|
||||
return en();
|
||||
switch (locale) {
|
||||
case "en":
|
||||
return _en;
|
||||
case "es":
|
||||
return _es;
|
||||
case "ja":
|
||||
return _ja;
|
||||
default:
|
||||
throw new Error(`Locale ${locale} not supported`);
|
||||
}
|
||||
|
||||
throw new Error(`Locale ${locale} not supported`);
|
||||
}
|
||||
return locale;
|
||||
};
|
||||
@@ -18,3 +26,17 @@ export const en = (locale?: DeepPartial<LocaleType>): LocaleType => {
|
||||
}
|
||||
return deepMerge(_en, locale);
|
||||
};
|
||||
|
||||
export const ja = (locale?: DeepPartial<LocaleType>): LocaleType => {
|
||||
if (!locale) {
|
||||
return _ja;
|
||||
}
|
||||
return deepMerge(_ja, locale);
|
||||
};
|
||||
|
||||
export const es = (locale?: DeepPartial<LocaleType>): LocaleType => {
|
||||
if (!locale) {
|
||||
return _es;
|
||||
}
|
||||
return deepMerge(_es, locale);
|
||||
};
|
||||
|
||||
@@ -1,111 +1,5 @@
|
||||
export type Locale = LocaleType | "en";
|
||||
import { _en } from "./en";
|
||||
|
||||
export type Locale = LocaleType | "en" | "es" | "ja";
|
||||
|
||||
export type LocaleType = typeof _en;
|
||||
|
||||
export const _en = {
|
||||
connect_wallet: {
|
||||
label: "Connect Wallet",
|
||||
},
|
||||
connect_wallet_details: {
|
||||
additional_actions: "Additional Actions",
|
||||
address_copied_clipboard: "Address copied to clipboard",
|
||||
backup_wallet: "Backup Wallet",
|
||||
backup_personal_wallet: "Backup personal wallet",
|
||||
import_wallet: "Import Wallet",
|
||||
connected_to_smart_wallet: "Connected to a Smart Wallet",
|
||||
current_network: "Current Network",
|
||||
backup: "Backup",
|
||||
connect_to_app: "Connect to App",
|
||||
guest: "Guest",
|
||||
connect: "Connect",
|
||||
new_to_wallets: "New to wallets?",
|
||||
view_transaction_history: "View Transaction History",
|
||||
get_started: "Get started",
|
||||
receive_funds: "Receive Funds",
|
||||
search_or_paste_token: "Search or paste token address",
|
||||
connect_a_wallet: "Connect a wallet",
|
||||
continue_as_guest: "Continue as guest",
|
||||
tos: "Terms of Service",
|
||||
privacy_policy: "Privacy Policy",
|
||||
by_connecting_you_agree: "By connecting, you agree to the",
|
||||
copy_address_or_scan:
|
||||
"Copy the wallet address or scan the QR code to send funds to this wallet.",
|
||||
request_testnet_funds: "Request Testnet Funds",
|
||||
your_address: "Your address",
|
||||
qr_code: "QR Code",
|
||||
select_token: "Select Token",
|
||||
send_to: "Send to",
|
||||
send_funds: "Send Funds",
|
||||
no_tokens_found: "No Tokens found",
|
||||
confirm_in_wallet: "Confirm in your wallet",
|
||||
select_network: "Select Network",
|
||||
switch_to: "Switch to",
|
||||
no_supported_chains_detected: "No supported chains detected",
|
||||
recommended: "Recommended",
|
||||
network_mismatch:
|
||||
"There's a network mismatch between your contract and your wallet",
|
||||
},
|
||||
connecting_wallet: {
|
||||
creating_encrypting:
|
||||
"Creating, encrypting and securing your device wallet.",
|
||||
connecting_your_wallet: "Connecting your wallet",
|
||||
connecting_through_pop_up:
|
||||
"Login and connect your app through the wallet pop-up",
|
||||
},
|
||||
local_wallet: {
|
||||
guest_wallet: "Guest Wallet",
|
||||
backup_your_wallet: "Backup your wallet",
|
||||
create_new_wallet: "Create new wallet",
|
||||
private_key_mnemonic: "Or Private key or Mnemonic",
|
||||
private_key_mnemonic_placeholder: "Private key / Mnemonic",
|
||||
application_can_authorize_transactions:
|
||||
"The application can authorize any transactions on behalf of the wallet without any approvals. We recommend only connecting to trusted applications.",
|
||||
double_check_password: "Please, double check your password or private key.",
|
||||
error_accessing_file: "Error accessing the file. Please try again.",
|
||||
wallet_address: "Wallet Address",
|
||||
this_will_download_json:
|
||||
"This will download a JSON file containing your wallet information onto your device encrypted with the password.",
|
||||
this_is_a_temporary_wallet:
|
||||
"This is a temporary guest wallet. Download a backup if you don't want to loose access to it.",
|
||||
},
|
||||
smart_wallet: {
|
||||
switch_to_smart: "Switch to Smart Wallet",
|
||||
switch_to_personal: "Switch to Personal Wallet",
|
||||
network_mismatch: "Network Mismatch",
|
||||
connecting: "Connecting",
|
||||
},
|
||||
embedded_wallet: {
|
||||
request_new_code: "Request new code",
|
||||
sign_in: "Sign In",
|
||||
sign_in_google: "Sign in with Google",
|
||||
enter_your_email: "Enter your email address",
|
||||
forgot_password: "Forgot password",
|
||||
enter_account_recovery_code: "Enter account recovery code",
|
||||
backup_your_account: "Backup your account",
|
||||
},
|
||||
wallet_connect: {
|
||||
no_results_found: "No results found",
|
||||
search_wallets: "Search Wallets",
|
||||
},
|
||||
common: {
|
||||
connect_app: "Connect app",
|
||||
unknown_network: "Unknown Network",
|
||||
fetching: "Fetching...",
|
||||
password: "Password",
|
||||
reject: "Reject",
|
||||
approve: "Approve",
|
||||
switch_network: "Switch Network",
|
||||
import: "Import",
|
||||
username: "Username",
|
||||
amount: "Amount",
|
||||
send: "Send",
|
||||
receive: "Receive",
|
||||
continue: "Continue",
|
||||
error_switching_network: "Error switching network",
|
||||
or: "OR",
|
||||
from: "from",
|
||||
to: "from",
|
||||
next: "Next",
|
||||
learn_more: "Learn More",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -30,6 +30,9 @@ export { useCoinbaseWallet } from "./wallets/hooks/useCoinbaseWallet";
|
||||
export { useMetaMaskWallet } from "./wallets/hooks/useMetaMaskWallet";
|
||||
export { useRainbowWallet } from "./wallets/hooks/useRainbowWallet";
|
||||
export { useTrustWallet } from "./wallets/hooks/useTrustWallet";
|
||||
export { useEmbeddedWallet } from "./wallets/hooks/useEmbeddedWallet";
|
||||
export { useSmartWallet } from "./wallets/hooks/useSmartWallet";
|
||||
export { useEmbeddedWalletSendVerificationEmail } from "./wallets/hooks/useEmbeddedWalletSendVerificationEmail";
|
||||
|
||||
export {
|
||||
ConnectWallet,
|
||||
@@ -39,13 +42,13 @@ export { Web3Button } from "./components/Web3Button";
|
||||
|
||||
// utilities
|
||||
export * from "./utils/uri";
|
||||
export * from "./utils/addresses";
|
||||
export { createSyncStorage as createLocalStorage } from "../core/AsyncStorage";
|
||||
export { createAsyncLocalStorage } from "../core/AsyncStorage";
|
||||
export { createSecureStorage } from "../core/SecureStorage";
|
||||
export { ThirdwebStorage } from "../core/storage/storage";
|
||||
|
||||
export * from "./i18n/strings";
|
||||
export * from "./i18n/types";
|
||||
|
||||
// ui components
|
||||
export * from "./components/base";
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { SmartWallet, walletIds } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
SmartWallet,
|
||||
WalletConnectHandler,
|
||||
WalletConnectReceiverConfig,
|
||||
WalletConnectV2Handler,
|
||||
walletIds,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
@@ -8,13 +14,15 @@ import {
|
||||
} from "react";
|
||||
import { useWalletConnectListener } from "../wallets/hooks/useWalletConnectListener";
|
||||
import { MagicLink } from "../wallets/wallets/MagicLink";
|
||||
import { useWalletContext } from "@thirdweb-dev/react-core";
|
||||
import { useWallet, useWalletContext } from "@thirdweb-dev/react-core";
|
||||
import { isWalletConnectReceiverEnabled } from "../wallets/utils";
|
||||
|
||||
type DappContextType = {
|
||||
smartWallet?: SmartWallet;
|
||||
setSmartWallet?: (value?: SmartWallet) => void;
|
||||
magicLink?: MagicLink;
|
||||
setMagicLink?: (value?: MagicLink) => void;
|
||||
walletConnectHandler?: WalletConnectHandler;
|
||||
};
|
||||
|
||||
const DappContext = createContext<DappContextType>({});
|
||||
@@ -22,15 +30,50 @@ const DappContext = createContext<DappContextType>({});
|
||||
export const DappContextProvider = (props: React.PropsWithChildren) => {
|
||||
const [smartWallet, setSmartWallet] = useState<SmartWallet | undefined>();
|
||||
const [magicLink, setMagicLink] = useState<MagicLink | undefined>();
|
||||
const [walletConnectHandler, setWalletConnectHandler] =
|
||||
useState<WalletConnectHandler>();
|
||||
const createdWalletInstance = useWalletContext().createdWalletInstance;
|
||||
const activeWallet = useWallet();
|
||||
|
||||
useEffect(() => {
|
||||
if (createdWalletInstance?.walletId === walletIds.magicLink) {
|
||||
if (!createdWalletInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (createdWalletInstance.walletId === walletIds.magicLink) {
|
||||
setMagicLink(createdWalletInstance as MagicLink);
|
||||
}
|
||||
}, [createdWalletInstance, setMagicLink]);
|
||||
|
||||
useWalletConnectListener();
|
||||
useEffect(() => {
|
||||
if (!activeWallet) {
|
||||
return;
|
||||
}
|
||||
|
||||
const initWCHandler = async () => {
|
||||
const wcReceiverOptions =
|
||||
activeWallet?.getOptions() as WalletConnectReceiverConfig;
|
||||
|
||||
const handler = new WalletConnectV2Handler(
|
||||
{
|
||||
walletConnectReceiver: {
|
||||
...(wcReceiverOptions?.walletConnectReceiver === true
|
||||
? {}
|
||||
: wcReceiverOptions?.walletConnectReceiver),
|
||||
},
|
||||
},
|
||||
activeWallet,
|
||||
);
|
||||
await handler.init();
|
||||
setWalletConnectHandler(handler);
|
||||
};
|
||||
|
||||
if (isWalletConnectReceiverEnabled(activeWallet)) {
|
||||
initWCHandler();
|
||||
}
|
||||
}, [activeWallet]);
|
||||
|
||||
useWalletConnectListener(walletConnectHandler);
|
||||
|
||||
const magicSDK = useCallback(() => {
|
||||
if (magicLink) {
|
||||
@@ -48,6 +91,7 @@ export const DappContextProvider = (props: React.PropsWithChildren) => {
|
||||
setSmartWallet,
|
||||
magicLink: magicLink,
|
||||
setMagicLink: setMagicLink,
|
||||
walletConnectHandler: walletConnectHandler,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
@@ -74,3 +118,9 @@ export const useMagicLink = () => {
|
||||
setMagicLink: context.setMagicLink,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export const useWalletConnectHandler = () => {
|
||||
const context = useContext(DappContext);
|
||||
|
||||
return context.walletConnectHandler;
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ interface ThirdwebProviderProps<TChains extends Chain[]>
|
||||
* />
|
||||
* ```
|
||||
*
|
||||
* * ```jsx
|
||||
* ```jsx
|
||||
* import { en } from "@thirdweb-dev/react-native";
|
||||
*
|
||||
* <ThirdwebProvider
|
||||
@@ -86,6 +86,7 @@ interface ThirdwebProviderProps<TChains extends Chain[]>
|
||||
* @example
|
||||
* You can wrap your application with the provider as follows:
|
||||
*
|
||||
* ```jsx
|
||||
* import { ThirdwebProvider } from "@thirdweb-dev/react-native";
|
||||
*
|
||||
* const App = () => {
|
||||
@@ -95,7 +96,7 @@ interface ThirdwebProviderProps<TChains extends Chain[]>
|
||||
* </ThirdwebProvider>
|
||||
* );
|
||||
* };
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
export const ThirdwebProvider = <
|
||||
TChains extends Chain[] = typeof defaultChains,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// import { Platform } from "react-native";
|
||||
|
||||
export const textVariants = {
|
||||
defaults: {
|
||||
fontFamily: undefined as string | undefined,
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { utils } from "ethers";
|
||||
|
||||
/**
|
||||
* Shortens an EVM compatible address to show the first 6 and last 4 characters
|
||||
*
|
||||
* @param str The address to shorten
|
||||
* @param extraShort If true, show the first 4 and last 3 characters
|
||||
* @returns The shortened address
|
||||
*/
|
||||
export function shortenWalletAddress(str?: string, extraShort = true) {
|
||||
if (!str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
return `${str.substring(0, extraShort ? 4 : 6)}...${str.substring(
|
||||
str.length - (extraShort ? 3 : 4),
|
||||
)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function shortens an address if it is a valid EVM address.
|
||||
*
|
||||
* @param address The address to shorten
|
||||
* @param extraShort If true, show the first 4 and last 3 characters
|
||||
* @returns The shortened address
|
||||
* @example
|
||||
* ```ts
|
||||
* const address = shortenIfAddress("0x1234567890123456789012345678901234567890", true); // result will be "0x1234...890"
|
||||
* ```
|
||||
*/
|
||||
export function shortenIfAddress(address?: string, extraShort?: true): string {
|
||||
if (!address) {
|
||||
return "";
|
||||
}
|
||||
if (isPossibleEVMAddress(address, true)) {
|
||||
return shortenWalletAddress(address, extraShort) || "";
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
export function isEnsName(name: string): boolean {
|
||||
return name?.endsWith(".eth");
|
||||
}
|
||||
|
||||
// if a string is a valid address or ens name
|
||||
export function isPossibleEVMAddress(address?: string, ignoreEns?: boolean) {
|
||||
if (!address) {
|
||||
return false;
|
||||
}
|
||||
if (isEnsName(address) && !ignoreEns) {
|
||||
return true;
|
||||
}
|
||||
return utils.isAddress(address);
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import { WCMeta } from "../wallets/types/wc";
|
||||
/**
|
||||
* Build a WalletConnect display URI from a wc:// uri + a wallet specific link
|
||||
*
|
||||
* @param uri The wc:// uri
|
||||
* @param links The wallet specific links
|
||||
* @param uri - The wc:// uri
|
||||
* @param links - The wallet specific links
|
||||
* @returns The WalletConnect display URI
|
||||
*/
|
||||
export function formatWalletConnectDisplayUri(
|
||||
|
||||
@@ -23,12 +23,12 @@ export type CoinbaseWalletConnectorOptions = WalletMobileSDKProviderOptions &
|
||||
ConfigurationParams & {
|
||||
/**
|
||||
* Fallback Ethereum JSON RPC URL
|
||||
* @default ""
|
||||
* @defaultValue ""
|
||||
*/
|
||||
jsonRpcUrl?: string;
|
||||
/**
|
||||
* Fallback Ethereum Chain ID
|
||||
* @default 1
|
||||
* @defaultValue 1
|
||||
*/
|
||||
chainId?: number;
|
||||
};
|
||||
|
||||
+149
-94
@@ -1,16 +1,18 @@
|
||||
import {
|
||||
AuthOptions,
|
||||
AuthParams,
|
||||
AuthResult,
|
||||
EmbeddedWalletConnectionArgs,
|
||||
EmbeddedWalletConnectorOptions,
|
||||
OauthOption,
|
||||
SendEmailOtpReturnType,
|
||||
} from "./types";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
import { Connector, normalizeChainId } from "@thirdweb-dev/wallets";
|
||||
import { providers, Signer } from "ethers";
|
||||
import { utils } from "ethers";
|
||||
import {
|
||||
customJwt,
|
||||
sendEmailOTP,
|
||||
sendVerificationEmail,
|
||||
socialLogin,
|
||||
validateEmailOTP,
|
||||
} from "./embedded/auth";
|
||||
@@ -21,7 +23,14 @@ import {
|
||||
getConnectedEmail,
|
||||
saveConnectedEmail,
|
||||
} from "./embedded/helpers/storage/local";
|
||||
import { AuthProvider } from "@paperxyz/embedded-wallet-service-sdk";
|
||||
import {
|
||||
AuthProvider,
|
||||
Connector,
|
||||
RecoveryShareManagement,
|
||||
UserWalletStatus,
|
||||
normalizeChainId,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { isValidUserManagedEmailOtp } from "./embedded/helpers/api/fetchers";
|
||||
|
||||
export class EmbeddedWalletConnector extends Connector<EmbeddedWalletConnectionArgs> {
|
||||
private options: EmbeddedWalletConnectorOptions;
|
||||
@@ -37,142 +46,184 @@ export class EmbeddedWalletConnector extends Connector<EmbeddedWalletConnectionA
|
||||
this.email = getConnectedEmail();
|
||||
}
|
||||
|
||||
async connect(options?: { chainId?: number } & EmbeddedWalletConnectionArgs) {
|
||||
const connected = await this.isConnected();
|
||||
|
||||
if (connected) {
|
||||
return this.getAddress();
|
||||
}
|
||||
|
||||
switch (options?.loginType) {
|
||||
case "headless_google_oauth":
|
||||
{
|
||||
await socialLogin(
|
||||
{
|
||||
provider: AuthProvider.GOOGLE,
|
||||
redirectUrl: options.redirectUrl,
|
||||
},
|
||||
this.options.clientId,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "headless_email_otp_verification": {
|
||||
await this.validateEmailOtp({ otp: options.otp });
|
||||
break;
|
||||
}
|
||||
case "jwt": {
|
||||
await this.customJwt({
|
||||
jwt: options.jwt,
|
||||
password: options.password,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error("Invalid login type");
|
||||
}
|
||||
|
||||
if (options?.chainId) {
|
||||
this.switchChain(options.chainId);
|
||||
async connect(options?: EmbeddedWalletConnectionArgs) {
|
||||
try {
|
||||
await this.getSigner();
|
||||
} catch (error) {
|
||||
throw new Error(`Error fetching the signer: ${error}`);
|
||||
}
|
||||
|
||||
this.setupListeners();
|
||||
|
||||
if (options?.chainId) {
|
||||
await this.switchChain(options.chainId);
|
||||
}
|
||||
|
||||
if (this.email) {
|
||||
saveConnectedEmail(this.email);
|
||||
}
|
||||
return this.getAddress();
|
||||
}
|
||||
|
||||
async validateEmailOtp(options: { otp: string }) {
|
||||
if (!this.email) {
|
||||
throw new Error("Email is required to connect");
|
||||
async authenticate(params: AuthParams): Promise<AuthResult> {
|
||||
const strategy = params.strategy;
|
||||
switch (strategy) {
|
||||
case "email_verification": {
|
||||
return await this.validateEmailOTP({
|
||||
email: params.email,
|
||||
otp: params.verificationCode,
|
||||
recoveryCode: params.recoveryCode,
|
||||
});
|
||||
}
|
||||
case "google": {
|
||||
return this.socialLogin({
|
||||
provider: AuthProvider.GOOGLE,
|
||||
redirectUrl: params.redirectUrl,
|
||||
});
|
||||
}
|
||||
case "facebook": {
|
||||
return this.socialLogin({
|
||||
provider: AuthProvider.FACEBOOK,
|
||||
redirectUrl: params.redirectUrl,
|
||||
});
|
||||
}
|
||||
case "apple": {
|
||||
return this.socialLogin({
|
||||
provider: AuthProvider.APPLE,
|
||||
redirectUrl: params.redirectUrl,
|
||||
});
|
||||
}
|
||||
case "jwt": {
|
||||
return this.customJwt({
|
||||
jwt: params.jwt,
|
||||
password: params.encryptionKey || "",
|
||||
});
|
||||
}
|
||||
default:
|
||||
assertUnreachable(strategy);
|
||||
}
|
||||
}
|
||||
|
||||
private async validateEmailOTP(options: {
|
||||
email: string;
|
||||
otp: string;
|
||||
recoveryCode?: string;
|
||||
}): Promise<AuthResult> {
|
||||
try {
|
||||
await validateEmailOTP({
|
||||
const { storedToken } = await validateEmailOTP({
|
||||
email: options.email,
|
||||
clientId: this.options.clientId,
|
||||
otp: options.otp,
|
||||
recoveryCode: options.recoveryCode,
|
||||
});
|
||||
return {
|
||||
user: {
|
||||
status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED,
|
||||
recoveryShareManagement:
|
||||
storedToken.authDetails.recoveryShareManagement,
|
||||
},
|
||||
isNewUser: storedToken.isNewUser,
|
||||
needsRecoveryCode:
|
||||
storedToken.authDetails.recoveryShareManagement ===
|
||||
RecoveryShareManagement.USER_MANAGED,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error while validating otp: ${error}`);
|
||||
if (error instanceof Error) {
|
||||
return { error: error.message };
|
||||
throw new Error(`Error while validating otp: ${error.message}`);
|
||||
} else {
|
||||
return { error: "An unknown error occurred" };
|
||||
throw new Error("An unknown error occurred while validating otp");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await this.getSigner();
|
||||
this.emit("connected");
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
return { error: error.message };
|
||||
} else {
|
||||
return { error: "Error getting the signer" };
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async sendEmailOtp(options: { email: string }) {
|
||||
async isValidUserManagedEmailOTP(options: { otp: string }) {
|
||||
try {
|
||||
const result = await isValidUserManagedEmailOtp({
|
||||
clientId: this.options.clientId,
|
||||
email: this.email || "",
|
||||
otp: options.otp,
|
||||
});
|
||||
|
||||
if (result.isValid) {
|
||||
return result;
|
||||
} else {
|
||||
throw new Error("Invalid otp, please try again.");
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error validating otp: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
async sendVerificationEmail(options: {
|
||||
email: string;
|
||||
}): Promise<SendEmailOtpReturnType> {
|
||||
this.email = options.email;
|
||||
saveConnectedEmail(options.email);
|
||||
return sendEmailOTP({
|
||||
return sendVerificationEmail({
|
||||
email: options.email,
|
||||
clientId: this.options.clientId,
|
||||
});
|
||||
}
|
||||
|
||||
async socialLogin(oauthOption: OauthOption) {
|
||||
private async socialLogin(oauthOption: OauthOption): Promise<AuthResult> {
|
||||
try {
|
||||
const { email } = await socialLogin(oauthOption, this.options.clientId);
|
||||
const { storedToken, email } = await socialLogin(
|
||||
oauthOption,
|
||||
this.options.clientId,
|
||||
);
|
||||
this.email = email;
|
||||
saveConnectedEmail(email);
|
||||
|
||||
return {
|
||||
user: {
|
||||
status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED,
|
||||
recoveryShareManagement:
|
||||
storedToken.authDetails.recoveryShareManagement,
|
||||
},
|
||||
isNewUser: storedToken.isNewUser,
|
||||
needsRecoveryCode:
|
||||
storedToken.authDetails.recoveryShareManagement ===
|
||||
RecoveryShareManagement.USER_MANAGED,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error while signing in with: ${oauthOption.provider}. ${error}`,
|
||||
);
|
||||
if (error instanceof Error) {
|
||||
return { error: error.message };
|
||||
throw new Error(
|
||||
`Error signing in with ${oauthOption.provider}: ${error.message}`,
|
||||
);
|
||||
} else {
|
||||
return { error: "An unknown error occurred" };
|
||||
throw new Error(
|
||||
`An unknown error occurred signing in with ${oauthOption.provider}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await this.getSigner();
|
||||
this.emit("connected");
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
return { error: error.message };
|
||||
} else {
|
||||
return { error: "Error getting the signer" };
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async customJwt(authOptions: AuthOptions) {
|
||||
private async customJwt(authOptions: AuthOptions): Promise<AuthResult> {
|
||||
try {
|
||||
const resp = await customJwt(authOptions, this.options.clientId);
|
||||
this.email = resp.email;
|
||||
const { verifiedToken, email } = await customJwt(
|
||||
authOptions,
|
||||
this.options.clientId,
|
||||
);
|
||||
this.email = email;
|
||||
return {
|
||||
user: {
|
||||
status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED,
|
||||
recoveryShareManagement:
|
||||
verifiedToken.authDetails.recoveryShareManagement,
|
||||
},
|
||||
isNewUser: verifiedToken.isNewUser,
|
||||
needsRecoveryCode:
|
||||
verifiedToken.authDetails.recoveryShareManagement ===
|
||||
RecoveryShareManagement.USER_MANAGED,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error while verifying auth: ${error}`);
|
||||
this.disconnect();
|
||||
throw error;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.getSigner();
|
||||
this.emit("connected");
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
return { error: error.message };
|
||||
} else {
|
||||
return { error: "Error getting the signer" };
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async disconnect(): Promise<void> {
|
||||
@@ -297,3 +348,7 @@ export class EmbeddedWalletConnector extends Connector<EmbeddedWalletConnectionA
|
||||
return this.email;
|
||||
}
|
||||
}
|
||||
|
||||
function assertUnreachable(x: never): never {
|
||||
throw new Error("Invalid param: " + x);
|
||||
}
|
||||
|
||||
+109
-66
@@ -1,14 +1,15 @@
|
||||
import type { CognitoUser } from "amazon-cognito-identity-js";
|
||||
|
||||
import {
|
||||
AuthProvider,
|
||||
AuthStoredTokenWithCookieReturnType,
|
||||
RecoveryShareManagement,
|
||||
} from "@paperxyz/embedded-wallet-service-sdk";
|
||||
import type { CognitoUser } from "amazon-cognito-identity-js";
|
||||
import { Auth } from "aws-amplify";
|
||||
|
||||
SendEmailOtpReturnType,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
generateAuthTokenFromCognitoEmailOtp,
|
||||
getEmbeddedWalletUserDetail,
|
||||
sendUserManagedEmailOtp,
|
||||
validateUserManagedEmailOtp,
|
||||
verifyClientId,
|
||||
} from "./helpers/api/fetchers";
|
||||
import {
|
||||
@@ -20,17 +21,17 @@ import {
|
||||
postPaperAuthUserManaged,
|
||||
prePaperAuth,
|
||||
} from "./helpers/auth/middleware";
|
||||
import { isDeviceSharePresentForUser } from "./helpers/storage/local";
|
||||
import { getCognitoUser, setCognitoUser } from "./helpers/storage/state";
|
||||
import { SendEmailOtpReturnType } from "@thirdweb-dev/wallets";
|
||||
import { InAppBrowser } from "react-native-inappbrowser-reborn";
|
||||
import { AuthOptions, OauthOption } from "../types";
|
||||
import { isDeviceSharePresentForUser } from "./helpers/storage/local";
|
||||
import { Auth } from "aws-amplify";
|
||||
import {
|
||||
ROUTE_AUTH_JWT_CALLBACK,
|
||||
ROUTE_HEADLESS_GOOGLE_LOGIN,
|
||||
ROUTE_HEADLESS_OAUTH_LOGIN,
|
||||
} from "./helpers/constants";
|
||||
import { AuthOptions, OauthOption, VerifiedTokenResponse } from "../types";
|
||||
import { InAppBrowser } from "react-native-inappbrowser-reborn";
|
||||
|
||||
export async function sendEmailOTP(options: {
|
||||
export async function sendVerificationEmail(options: {
|
||||
email: string;
|
||||
clientId: string;
|
||||
}): Promise<SendEmailOtpReturnType> {
|
||||
@@ -41,16 +42,6 @@ export async function sendEmailOTP(options: {
|
||||
email: options.email,
|
||||
});
|
||||
|
||||
// AWS Auth flow
|
||||
let cognitoUser: CognitoUser;
|
||||
try {
|
||||
cognitoUser = await cognitoEmailSignIn(options.email, options.clientId);
|
||||
} catch (e) {
|
||||
await cognitoEmailSignUp(options.email, options.clientId);
|
||||
cognitoUser = await cognitoEmailSignIn(options.email, options.clientId);
|
||||
}
|
||||
setCognitoUser(cognitoUser);
|
||||
|
||||
let result: Awaited<ReturnType<typeof getEmbeddedWalletUserDetail>>;
|
||||
try {
|
||||
result = await getEmbeddedWalletUserDetail({
|
||||
@@ -63,11 +54,29 @@ export async function sendEmailOTP(options: {
|
||||
);
|
||||
}
|
||||
|
||||
if (result.recoveryShareManagement === "USER_MANAGED") {
|
||||
try {
|
||||
await sendUserManagedEmailOtp(options.email, options.clientId);
|
||||
} catch (error) {
|
||||
throw new Error(`Error sending user managed email otp: ${error}`);
|
||||
}
|
||||
} else {
|
||||
// CLOUD_MANAGED
|
||||
let cognitoUser: CognitoUser;
|
||||
try {
|
||||
cognitoUser = await cognitoEmailSignIn(options.email, options.clientId);
|
||||
} catch (e) {
|
||||
await cognitoEmailSignUp(options.email, options.clientId);
|
||||
cognitoUser = await cognitoEmailSignIn(options.email, options.clientId);
|
||||
}
|
||||
setCognitoUser(cognitoUser);
|
||||
}
|
||||
|
||||
return result.isNewUser
|
||||
? {
|
||||
isNewUser: result.isNewUser,
|
||||
isNewDevice: true,
|
||||
recoveryShareManagement: RecoveryShareManagement.AWS_MANAGED,
|
||||
recoveryShareManagement: result.recoveryShareManagement,
|
||||
}
|
||||
: {
|
||||
isNewUser: result.isNewUser,
|
||||
@@ -75,76 +84,103 @@ export async function sendEmailOTP(options: {
|
||||
options.clientId,
|
||||
result.walletUserId ?? "",
|
||||
)),
|
||||
recoveryShareManagement: RecoveryShareManagement.AWS_MANAGED,
|
||||
recoveryShareManagement: result.recoveryShareManagement,
|
||||
};
|
||||
}
|
||||
|
||||
export async function validateEmailOTP({
|
||||
clientId,
|
||||
otp,
|
||||
}: {
|
||||
export async function validateEmailOTP(options: {
|
||||
email: string;
|
||||
otp: string;
|
||||
clientId: string;
|
||||
recoveryCode?: string;
|
||||
}): Promise<AuthStoredTokenWithCookieReturnType> {
|
||||
let verifiedToken: Awaited<
|
||||
ReturnType<typeof generateAuthTokenFromCognitoEmailOtp>
|
||||
>["verifiedToken"];
|
||||
let verifiedTokenJwtString: string;
|
||||
|
||||
let result: Awaited<ReturnType<typeof getEmbeddedWalletUserDetail>>;
|
||||
try {
|
||||
let cognitoUser = getCognitoUser();
|
||||
if (!cognitoUser) {
|
||||
throw new Error("MISSING COGNITO USER");
|
||||
}
|
||||
cognitoUser = await Auth.sendCustomChallengeAnswer(cognitoUser, otp);
|
||||
|
||||
// It we get here, the answer was sent successfully,
|
||||
// but it might have been wrong (1st or 2nd time)
|
||||
// So we should test if the user is authenticated now
|
||||
const session = await Auth.currentSession();
|
||||
|
||||
({ verifiedToken, verifiedTokenJwtString } =
|
||||
await generateAuthTokenFromCognitoEmailOtp(session, clientId));
|
||||
result = await getEmbeddedWalletUserDetail({
|
||||
email: options.email,
|
||||
clientId: options.clientId,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid OTP ${e}`);
|
||||
throw new Error(
|
||||
`Malformed response from the send email OTP API: ${JSON.stringify(e)}`,
|
||||
);
|
||||
}
|
||||
let verifiedTokenResponse: VerifiedTokenResponse;
|
||||
|
||||
if (result.recoveryShareManagement === "USER_MANAGED") {
|
||||
try {
|
||||
verifiedTokenResponse = await validateUserManagedEmailOtp({
|
||||
email: options.email,
|
||||
otp: options.otp,
|
||||
clientId: options.clientId,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`Error validating user managed email otp: ${error}`);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let cognitoUser = getCognitoUser();
|
||||
if (!cognitoUser) {
|
||||
throw new Error("MISSING COGNITO USER");
|
||||
}
|
||||
cognitoUser = await Auth.sendCustomChallengeAnswer(
|
||||
cognitoUser,
|
||||
options.otp,
|
||||
);
|
||||
|
||||
// It we get here, the answer was sent successfully,
|
||||
// but it might have been wrong (1st or 2nd time)
|
||||
// So we should test if the user is authenticated now
|
||||
const session = await Auth.currentSession();
|
||||
|
||||
verifiedTokenResponse = await generateAuthTokenFromCognitoEmailOtp(
|
||||
session,
|
||||
options.clientId,
|
||||
);
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid OTP ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const storedToken: AuthStoredTokenWithCookieReturnType["storedToken"] = {
|
||||
jwtToken: verifiedToken.jwtToken,
|
||||
authDetails: verifiedToken.authDetails,
|
||||
authProvider: verifiedToken.authProvider,
|
||||
developerClientId: verifiedToken.developerClientId,
|
||||
cookieString: verifiedTokenJwtString,
|
||||
jwtToken: verifiedTokenResponse.verifiedToken.jwtToken,
|
||||
authDetails: verifiedTokenResponse.verifiedToken.authDetails,
|
||||
authProvider: verifiedTokenResponse.verifiedToken.authProvider,
|
||||
developerClientId: verifiedTokenResponse.verifiedToken.developerClientId,
|
||||
cookieString: verifiedTokenResponse.verifiedTokenJwtString,
|
||||
// we should always store the jwt cookie since there's no concept of cookie in react native
|
||||
shouldStoreCookieString: true,
|
||||
isNewUser: verifiedToken.isNewUser,
|
||||
isNewUser: verifiedTokenResponse.verifiedToken.isNewUser,
|
||||
};
|
||||
|
||||
await postPaperAuth(storedToken, clientId);
|
||||
await postPaperAuth({
|
||||
storedToken,
|
||||
clientId: options.clientId,
|
||||
recoveryCode: options.recoveryCode,
|
||||
});
|
||||
|
||||
return { storedToken };
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Malformed response from the verify one time password: ${JSON.stringify(
|
||||
e,
|
||||
)}`,
|
||||
`Malformed response from the verify one time password: ${
|
||||
(e as Error).message
|
||||
}}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function socialLogin(oauthOptions: OauthOption, clientId: string) {
|
||||
const headlessLoginLinkWithParams = `${ROUTE_HEADLESS_GOOGLE_LOGIN}?authProvider=${encodeURIComponent(
|
||||
oauthOptions.provider,
|
||||
)}&baseUrl=${encodeURIComponent(
|
||||
"https://embedded-wallet.thirdweb.com",
|
||||
const encodedProvider = encodeURIComponent(oauthOptions.provider);
|
||||
const headlessLoginLinkWithParams = `${ROUTE_HEADLESS_OAUTH_LOGIN}?authProvider=${encodedProvider}&baseUrl=${encodeURIComponent(
|
||||
`https://embedded-wallet.thirdweb.com`,
|
||||
)}&platform=${encodeURIComponent("mobile")}`;
|
||||
|
||||
const resp = await fetch(headlessLoginLinkWithParams);
|
||||
|
||||
if (!resp.ok) {
|
||||
const error = await resp.json();
|
||||
throw new Error(`Error getting headless login link: ${error.message}`);
|
||||
throw new Error(`Error getting headless sign in link: ${error.message}`);
|
||||
}
|
||||
|
||||
const json = await resp.json();
|
||||
@@ -155,7 +191,7 @@ export async function socialLogin(oauthOptions: OauthOption, clientId: string) {
|
||||
clientId || "",
|
||||
)}&platform=${encodeURIComponent("mobile")}&redirectUrl=${encodeURIComponent(
|
||||
oauthOptions.redirectUrl,
|
||||
)}`;
|
||||
)}&authOption=${encodedProvider}`;
|
||||
|
||||
const result = await InAppBrowser.openAuth(
|
||||
completeLoginUrl,
|
||||
@@ -170,16 +206,23 @@ export async function socialLogin(oauthOptions: OauthOption, clientId: string) {
|
||||
},
|
||||
);
|
||||
|
||||
if (result.type === "cancel") {
|
||||
throw new Error(`Sign in cancelled`);
|
||||
}
|
||||
|
||||
if (result.type !== "success") {
|
||||
throw new Error("Error signing in. Please try again later.");
|
||||
throw new Error(`Can't sign in with ${oauthOptions.provider}: ${result}`);
|
||||
}
|
||||
|
||||
const decodedUrl = decodeURIComponent(result.url);
|
||||
|
||||
const parts = decodedUrl.split("?authResult=");
|
||||
if (parts.length < 2) {
|
||||
throw new Error("Malformed response from the login redirect");
|
||||
// assume error
|
||||
const error = decodedUrl.split("?error=")?.[1];
|
||||
throw new Error(`Something went wrong. Please, try again later: ${error}`);
|
||||
}
|
||||
|
||||
const authResult = parts[1];
|
||||
const { storedToken } = JSON.parse(authResult);
|
||||
|
||||
@@ -195,7 +238,7 @@ export async function socialLogin(oauthOptions: OauthOption, clientId: string) {
|
||||
isNewUser: storedToken.isNewUser,
|
||||
};
|
||||
|
||||
await postPaperAuth(toStoreToken, clientId);
|
||||
await postPaperAuth({ storedToken: toStoreToken, clientId });
|
||||
|
||||
return { storedToken, email: storedToken.authDetails.email };
|
||||
} catch (e) {
|
||||
@@ -218,7 +261,7 @@ export async function customJwt(authOptions: AuthOptions, clientId: string) {
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const error = await resp.json();
|
||||
throw new Error(`JWT authentication error: ${error.message} `);
|
||||
throw new Error(`JWT authentication error: ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
+90
-20
@@ -1,16 +1,23 @@
|
||||
import {
|
||||
AuthProvider,
|
||||
RecoveryShareManagement,
|
||||
} from "@paperxyz/embedded-wallet-service-sdk";
|
||||
import { CognitoUserSession } from "amazon-cognito-identity-js";
|
||||
import {
|
||||
ROUTE_GET_EMBEDDED_WALLET_DETAILS,
|
||||
ROUTE_STORE_USER_SHARES,
|
||||
ROUTE_VERIFY_THIRDWEB_CLIENT_ID,
|
||||
ROUTE_VERIFY_COGNITO_OTP,
|
||||
ROUTE_USER_MANAGED_OTP,
|
||||
ROUTE_VALIDATE_USER_MANAGED_OTP,
|
||||
ROUTE_IS_VALID_USER_MANAGED_OTP,
|
||||
} from "../constants";
|
||||
import { getAuthTokenClient } from "../storage/local";
|
||||
import * as Application from "expo-application";
|
||||
import {
|
||||
RecoveryShareManagement,
|
||||
UserWalletStatus,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
IsValidUserManagedEmailOTPResponse,
|
||||
VerifiedTokenResponse,
|
||||
} from "../../../types";
|
||||
|
||||
const EMBEDDED_WALLET_TOKEN_HEADER = "embedded-wallet-token";
|
||||
const PAPER_CLIENT_ID_HEADER = "x-thirdweb-client-id";
|
||||
@@ -91,11 +98,14 @@ export async function getEmbeddedWalletUserDetail(args: {
|
||||
| {
|
||||
isNewUser: true;
|
||||
recoveryShareManagement: RecoveryShareManagement;
|
||||
status: UserWalletStatus;
|
||||
walletUserId: string;
|
||||
}
|
||||
| {
|
||||
isNewUser: false;
|
||||
walletUserId: string;
|
||||
recoveryShareManagement: RecoveryShareManagement;
|
||||
status: UserWalletStatus;
|
||||
};
|
||||
return result;
|
||||
}
|
||||
@@ -125,22 +135,82 @@ export async function generateAuthTokenFromCognitoEmailOtp(
|
||||
);
|
||||
}
|
||||
const respJ = await resp.json();
|
||||
return respJ as {
|
||||
verifiedToken: {
|
||||
jwtToken: string;
|
||||
authProvider: AuthProvider;
|
||||
developerClientId: string;
|
||||
authDetails: {
|
||||
email?: string;
|
||||
userWalletId: string;
|
||||
recoveryCode?: string;
|
||||
cookieString?: string;
|
||||
recoveryShareManagement: RecoveryShareManagement;
|
||||
};
|
||||
isNewUser: boolean;
|
||||
};
|
||||
verifiedTokenJwtString: string;
|
||||
};
|
||||
return respJ as VerifiedTokenResponse;
|
||||
}
|
||||
|
||||
export async function sendUserManagedEmailOtp(email: string, clientId: string) {
|
||||
const resp = await fetch(ROUTE_USER_MANAGED_OTP, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
[BUNDLE_ID_HEADER]: APP_BUNDLE_ID,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
clientId,
|
||||
}),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const error = await resp.json();
|
||||
throw new Error(
|
||||
`Something went wrong generating auth token from user cognito email otp. ${error.message}`,
|
||||
);
|
||||
}
|
||||
const respJ = await resp.json();
|
||||
return respJ;
|
||||
}
|
||||
|
||||
export async function validateUserManagedEmailOtp(options: {
|
||||
email: string;
|
||||
otp: string;
|
||||
clientId: string;
|
||||
}) {
|
||||
const resp = await fetch(ROUTE_VALIDATE_USER_MANAGED_OTP, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
[BUNDLE_ID_HEADER]: APP_BUNDLE_ID,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: options.email,
|
||||
otp: options.otp,
|
||||
clientId: options.clientId,
|
||||
}),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const error = await resp.json();
|
||||
throw new Error(
|
||||
`Something went wrong generating auth token from user cognito email otp. ${error.message}`,
|
||||
);
|
||||
}
|
||||
const respJ = await resp.json();
|
||||
return respJ as VerifiedTokenResponse;
|
||||
}
|
||||
export async function isValidUserManagedEmailOtp(options: {
|
||||
email: string;
|
||||
otp: string;
|
||||
clientId: string;
|
||||
}) {
|
||||
const resp = await fetch(ROUTE_IS_VALID_USER_MANAGED_OTP, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
[BUNDLE_ID_HEADER]: APP_BUNDLE_ID,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: options.email,
|
||||
otp: options.otp,
|
||||
clientId: options.clientId,
|
||||
}),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const error = await resp.json();
|
||||
throw new Error(
|
||||
`Something went wrong generating auth token from user cognito email otp. ${error.message}`,
|
||||
);
|
||||
}
|
||||
const respJ = await resp.json();
|
||||
return respJ as IsValidUserManagedEmailOTPResponse;
|
||||
}
|
||||
|
||||
export async function storeUserShares({
|
||||
|
||||
+95
-20
@@ -1,7 +1,8 @@
|
||||
import {
|
||||
AuthProvider,
|
||||
AuthStoredTokenWithCookieReturnType,
|
||||
} from "@paperxyz/embedded-wallet-service-sdk";
|
||||
RecoveryShareManagement,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
getDeviceShare,
|
||||
setAuthTokenClient,
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
import { setUpNewUserWallet } from "../wallet/creation";
|
||||
import { getCognitoRecoveryPassword } from "../wallet/recoveryCode";
|
||||
import { setUpShareForNewDevice } from "../wallet/retrieval";
|
||||
import { ErrorMessages } from "../errors";
|
||||
|
||||
export async function prePaperAuth(args: {
|
||||
authenticationMethod: AuthProvider;
|
||||
@@ -19,10 +21,15 @@ export async function prePaperAuth(args: {
|
||||
Promise.resolve(args);
|
||||
}
|
||||
|
||||
export async function postPaperAuth(
|
||||
storedToken: AuthStoredTokenWithCookieReturnType["storedToken"],
|
||||
clientId: string,
|
||||
) {
|
||||
export async function postPaperAuth({
|
||||
storedToken,
|
||||
clientId,
|
||||
recoveryCode,
|
||||
}: {
|
||||
storedToken: AuthStoredTokenWithCookieReturnType["storedToken"];
|
||||
clientId: string;
|
||||
recoveryCode?: string;
|
||||
}) {
|
||||
if (storedToken.shouldStoreCookieString) {
|
||||
await setAuthTokenClient(storedToken.cookieString, clientId);
|
||||
}
|
||||
@@ -34,23 +41,32 @@ export async function postPaperAuth(
|
||||
});
|
||||
|
||||
if (storedToken.isNewUser) {
|
||||
console.log("========== New User ==========");
|
||||
const recoveryCode = await getCognitoRecoveryPassword(clientId);
|
||||
await setUpNewUserWallet(recoveryCode, clientId);
|
||||
const _recoveryCode = await getRecoveryCode(
|
||||
storedToken,
|
||||
clientId,
|
||||
recoveryCode,
|
||||
);
|
||||
if (!_recoveryCode) {
|
||||
throw new Error(ErrorMessages.missingRecoveryCode);
|
||||
}
|
||||
await setUpNewUserWallet(_recoveryCode, clientId);
|
||||
} else {
|
||||
try {
|
||||
// existing device share
|
||||
await getDeviceShare(clientId);
|
||||
console.log("========== Existing user with device share ==========");
|
||||
} catch (e) {
|
||||
// trying to recreate device share from recovery code to derive wallet
|
||||
const recoveryCode = await getCognitoRecoveryPassword(clientId);
|
||||
console.log("========== Existing user on new device ==========");
|
||||
|
||||
const _recoveryCode = await getRecoveryCode(
|
||||
storedToken,
|
||||
clientId,
|
||||
recoveryCode,
|
||||
);
|
||||
if (!_recoveryCode) {
|
||||
throw new Error(ErrorMessages.missingRecoveryCode);
|
||||
}
|
||||
try {
|
||||
await setUpShareForNewDevice({
|
||||
clientId,
|
||||
recoveryCode,
|
||||
recoveryCode: _recoveryCode,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error setting up wallet on device", error);
|
||||
@@ -67,6 +83,8 @@ export async function postPaperAuthUserManaged(
|
||||
clientId: string,
|
||||
password: string,
|
||||
) {
|
||||
const _password = await getRecoveryCode(storedToken, clientId, password);
|
||||
|
||||
if (storedToken.shouldStoreCookieString) {
|
||||
await setAuthTokenClient(storedToken.cookieString, clientId);
|
||||
}
|
||||
@@ -78,21 +96,17 @@ export async function postPaperAuthUserManaged(
|
||||
});
|
||||
|
||||
if (storedToken.isNewUser) {
|
||||
console.log("========== New User ==========");
|
||||
await setUpNewUserWallet(password, clientId);
|
||||
await setUpNewUserWallet(_password, clientId);
|
||||
} else {
|
||||
try {
|
||||
// existing device share
|
||||
await getDeviceShare(clientId);
|
||||
console.log("========== Existing user with device share ==========");
|
||||
} catch (e) {
|
||||
// trying to recreate device share from recovery code to derive wallet
|
||||
console.log("========== Existing user on new device ==========");
|
||||
|
||||
try {
|
||||
await setUpShareForNewDevice({
|
||||
clientId,
|
||||
recoveryCode: password,
|
||||
recoveryCode: _password,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error setting up wallet on device", error);
|
||||
@@ -103,3 +117,64 @@ export async function postPaperAuthUserManaged(
|
||||
|
||||
return storedToken;
|
||||
}
|
||||
|
||||
async function getRecoveryCode(
|
||||
storedToken: AuthStoredTokenWithCookieReturnType["storedToken"],
|
||||
clientId: string,
|
||||
recoveryCode?: string,
|
||||
): Promise<string> {
|
||||
if (
|
||||
storedToken.authDetails.recoveryShareManagement ===
|
||||
RecoveryShareManagement.CLOUD_MANAGED
|
||||
) {
|
||||
if (storedToken.authProvider === AuthProvider.CUSTOM_JWT) {
|
||||
// derive sub here
|
||||
const code = extractSubFromJwt(storedToken.jwtToken);
|
||||
if (!code) {
|
||||
throw new Error(
|
||||
`GetRecoveryCode error: ${ErrorMessages.missingRecoveryCode}`,
|
||||
);
|
||||
}
|
||||
return code;
|
||||
} else {
|
||||
try {
|
||||
const code = await getCognitoRecoveryPassword(clientId);
|
||||
return code;
|
||||
} catch (e) {
|
||||
throw new Error("Something went wrong getting cognito recovery code");
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
storedToken.authDetails.recoveryShareManagement ===
|
||||
RecoveryShareManagement.USER_MANAGED
|
||||
) {
|
||||
if (recoveryCode) {
|
||||
return recoveryCode;
|
||||
}
|
||||
throw new Error(ErrorMessages.missingRecoveryCode);
|
||||
} else {
|
||||
throw new Error("Invalid recovery share management option");
|
||||
}
|
||||
}
|
||||
|
||||
function extractSubFromJwt(jwtToken: string): string | undefined {
|
||||
const parts = jwtToken.split(".");
|
||||
if (parts.length !== 3) {
|
||||
throw new Error("Invalid JWT format.");
|
||||
}
|
||||
|
||||
const encodedPayload = parts[1];
|
||||
if (!encodedPayload) {
|
||||
throw new Error("Invalid JWT format.");
|
||||
}
|
||||
const decodedPayload = Buffer.from(encodedPayload, "base64").toString("utf8");
|
||||
|
||||
try {
|
||||
const payloadObject = JSON.parse(decodedPayload);
|
||||
if (payloadObject && payloadObject.sub) {
|
||||
return payloadObject.sub;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error("Error parsing JWT payload as JSON.");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -25,11 +25,16 @@ const ROUTE_2023_10_20_API_BASE_PATH = `${BASE_URL_2023}api/2023-10-20`;
|
||||
export const ROUTE_GET_EMBEDDED_WALLET_DETAILS = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/embedded-wallet-user-details`;
|
||||
export const ROUTE_VERIFY_COGNITO_OTP = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/validate-cognito-email-otp`;
|
||||
export const ROUTE_COGNITO_IDENTITY_POOL_URL = `cognito-idp.${AWS_REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}`;
|
||||
|
||||
export const ROUTE_STORE_USER_SHARES = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/embedded-wallet-shares`;
|
||||
export const ROUTE_GET_USER_SHARES = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/embedded-wallet-shares`;
|
||||
export const ROUTE_VERIFY_THIRDWEB_CLIENT_ID = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/verify-thirdweb-client-id`;
|
||||
export const ROUTE_AUTH_JWT_CALLBACK = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/validate-custom-jwt`;
|
||||
|
||||
export const ROUTE_HEADLESS_GOOGLE_LOGIN = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/headless-oauth-login-link`;
|
||||
export const ROUTE_USER_MANAGED_OTP = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/send-user-managed-email-otp`;
|
||||
export const ROUTE_VALIDATE_USER_MANAGED_OTP = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/validate-thirdweb-email-otp`;
|
||||
export const ROUTE_IS_VALID_USER_MANAGED_OTP = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/is-thirdweb-email-otp-valid`;
|
||||
|
||||
export const ROUTE_HEADLESS_OAUTH_LOGIN = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/headless-oauth-login-link`;
|
||||
|
||||
export const ROUTE_AUTH_COGNITO_ID_TOKEN = `${ROUTE_2023_10_20_API_BASE_PATH}/embedded-wallet/cognito-id-token`;
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
export const ErrorMessages = {
|
||||
invalidOtp:
|
||||
"Your OTP code is invalid or expired. Please request a new code or try again.",
|
||||
missingRecoveryCode: "Missing encryption key for user",
|
||||
};
|
||||
+3
-3
@@ -91,9 +91,9 @@ function createWalletShares(): {
|
||||
|
||||
/**
|
||||
* Store user's wallet shares. Encrypts authShare and recoveryShare as given clientSide as well.
|
||||
* @param {string} walletAddress the user's wallet address. Note that for each logged in user and clientId, we have a single walletAddress. This will error if we attempt to store shares for user's with an existing wallet different from the walletAddress
|
||||
* @param {string} authShare the *unencrypted* authShare for the user
|
||||
* @param {string} recoveryShare the *unencrypted* recovery share for the user
|
||||
* @param walletAddress - the user's wallet address. Note that for each logged in user and clientId, we have a single walletAddress. This will error if we attempt to store shares for user's with an existing wallet different from the walletAddress
|
||||
* @param authShare - the *unencrypted* authShare for the user
|
||||
* @param recoveryShare - the *unencrypted* recovery share for the user
|
||||
* @throws if another walletAddress already exists
|
||||
*/
|
||||
export async function storeShares<R extends string | undefined>({
|
||||
|
||||
+2
-2
@@ -46,9 +46,9 @@ export async function getExistingUserEtherJsWallet(clientId: string) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param deviceShare retrieves the current share associated with the user's device.
|
||||
* @param deviceShare - retrieves the current share associated with the user's device.
|
||||
* @returns the requested shares
|
||||
* @throws if attempting to get {@param deviceShare} when it's not present
|
||||
* @throws if attempting to get deviceShare when it's not present
|
||||
*/
|
||||
export async function getShares<
|
||||
A extends boolean,
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { getDefaultProvider } from "ethers";
|
||||
import { getExistingUserEtherJsWallet } from "./helpers/wallet/retrieval";
|
||||
|
||||
export async function getEthersSigner(clientId: string) {
|
||||
const wallet = await getExistingUserEtherJsWallet(clientId);
|
||||
const newWallet = wallet.connect(getDefaultProvider());
|
||||
|
||||
await newWallet.getChainId();
|
||||
return newWallet;
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Chain } from "@thirdweb-dev/chains";
|
||||
import { WalletOptions } from "@thirdweb-dev/wallets";
|
||||
import type {
|
||||
RecoveryShareManagement,
|
||||
PaperConstructorType,
|
||||
import {
|
||||
AuthProvider,
|
||||
} from "@paperxyz/embedded-wallet-service-sdk";
|
||||
RecoveryShareManagement,
|
||||
UserWalletStatus,
|
||||
WalletOptions,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
|
||||
export type OauthOptions = {
|
||||
providers: AuthProvider[];
|
||||
@@ -29,14 +29,7 @@ export type EmbeddedWalletOptions = Omit<
|
||||
>;
|
||||
|
||||
type EmbeddedAdvanceOptions = {
|
||||
recoveryShareManagement?: "USER_MANAGED" | "AWS_MANAGED";
|
||||
};
|
||||
|
||||
export type EmbeddedWalletAdditionalOptions = {
|
||||
emailClientId: string;
|
||||
chain: Pick<Chain, "chainId" | "rpc">;
|
||||
advancedOptions?: EmbeddedAdvanceOptions;
|
||||
styles?: PaperConstructorType<RecoveryShareManagement>["styles"];
|
||||
recoveryShareManagement?: RecoveryShareManagement;
|
||||
};
|
||||
|
||||
export interface EmbeddedWalletConnectorOptions {
|
||||
@@ -44,7 +37,6 @@ export interface EmbeddedWalletConnectorOptions {
|
||||
chain: Pick<Chain, "chainId" | "rpc">;
|
||||
chains: Chain[];
|
||||
advancedOptions?: EmbeddedAdvanceOptions;
|
||||
styles?: PaperConstructorType<RecoveryShareManagement>["styles"];
|
||||
}
|
||||
|
||||
export interface AuthOptions {
|
||||
@@ -52,21 +44,70 @@ export interface AuthOptions {
|
||||
password: string;
|
||||
}
|
||||
|
||||
export type SendEmailOtpReturnType = {
|
||||
isNewUser: boolean;
|
||||
isNewDevice: boolean;
|
||||
recoveryShareManagement: RecoveryShareManagement;
|
||||
};
|
||||
|
||||
export type EmbeddedWalletConnectionArgs = {
|
||||
chainId?: number;
|
||||
} & (
|
||||
| {
|
||||
loginType: "headless_google_oauth";
|
||||
redirectUrl: string;
|
||||
}
|
||||
| {
|
||||
loginType: "headless_email_otp_verification";
|
||||
email: string;
|
||||
otp: string;
|
||||
}
|
||||
| {
|
||||
loginType: "jwt";
|
||||
jwt: string;
|
||||
password: string;
|
||||
}
|
||||
);
|
||||
authResult: AuthResult;
|
||||
};
|
||||
|
||||
type EmailVerificationAuthParams = {
|
||||
strategy: "email_verification";
|
||||
email: string;
|
||||
verificationCode: string;
|
||||
recoveryCode?: string;
|
||||
};
|
||||
|
||||
type SocialAuthParams = {
|
||||
strategy: "google" | "facebook" | "apple";
|
||||
redirectUrl: string;
|
||||
};
|
||||
|
||||
type JwtAuthParams = {
|
||||
strategy: "jwt";
|
||||
jwt: string;
|
||||
encryptionKey?: string;
|
||||
};
|
||||
|
||||
// this is the input to 'authenticate'
|
||||
export type AuthParams =
|
||||
| EmailVerificationAuthParams
|
||||
| SocialAuthParams
|
||||
| JwtAuthParams;
|
||||
|
||||
// TODO typed based off AuthParams["strategy"]
|
||||
export type AuthResult = {
|
||||
user?: InitializedUser;
|
||||
isNewUser?: boolean;
|
||||
needsRecoveryCode?: boolean;
|
||||
};
|
||||
|
||||
export type InitializedUser = {
|
||||
status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED;
|
||||
recoveryShareManagement: RecoveryShareManagement;
|
||||
};
|
||||
|
||||
export type VerifiedTokenResponse = {
|
||||
verifiedToken: {
|
||||
jwtToken: string;
|
||||
authProvider: AuthProvider;
|
||||
developerClientId: string;
|
||||
authDetails: {
|
||||
email?: string;
|
||||
userWalletId: string;
|
||||
recoveryCode?: string;
|
||||
cookieString?: string;
|
||||
recoveryShareManagement: RecoveryShareManagement;
|
||||
};
|
||||
isNewUser: boolean;
|
||||
};
|
||||
verifiedTokenJwtString: string;
|
||||
};
|
||||
|
||||
export type IsValidUserManagedEmailOTPResponse = {
|
||||
isValid: { type: "boolean" };
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user