Compare commits

...
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
cbfd445ae7 Version Packages (#1784)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-16 20:38:41 -07:00
Jonas DanielsandGitHub 137f46a547 chore(chains): fix up chain sync script (#1783) 2023-10-17 02:28:33 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
1b8accde30 Version Packages (#1782)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-16 15:51:35 -07:00
Joaquim VergesandGitHub 07544252b4 [SDK] expose utility functions for abi / sources (#1781) 2023-10-16 22:43:13 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
8708519cad Version Packages (#1772)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-16 12:57:26 -07:00
Joaquim VergesandGitHub 6c30b7efc7 [ContractsJS] update contracts-js package (#1771) 2023-10-16 19:50:17 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
8b5e344f72 Version Packages (#1768)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-16 09:26:13 -07:00
Manan TankandGitHub 010955ff5c [react] - Fix OTP input not working well with Japanese keyboard (#1769) 2023-10-16 15:41:54 +00:00
Joaquim VergesandGitHub 956b5645e4 [SDK] Enable adding smart wallet admins with signature (#1756) 2023-10-15 23:46:45 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
068db44603 Version Packages (#1761)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-14 17:18:54 -07:00
Manan TankandGitHub dd7d0fca2d [react] Fix missing "Continue as Guest" button in ConnectWallet in Social+Guest setup (#1766) 2023-10-14 23:29:07 +00:00
Kien NgoandGitHub 526176c471 [SDK] Perf improv to marketplace methods (#1764) 2023-10-14 21:18:11 +00:00
Kien NgoandGitHub 09120c923c [SDK] Perf improv for getDeploymentInfo (#1765) 2023-10-14 18:12:19 +00:00
Kien NgoandGitHub d1f8e95162 [SDK] Perf improve to fetchPublishedContractFromPolygon() (#1763) 2023-10-14 14:29:09 +00:00
Kien NgoandGitHub 6573556d0e [SDK] Perf improv for drop-claim-conditions (#1762) 2023-10-13 22:53:35 +00:00
iketwandGitHub fc62b91ee5 [RN] Adds Signing with Google to EmbeddedWallet (#1724) 2023-10-13 18:51:47 +00:00
Kien NgoandGitHub 08e9cd206b [React/React Native] Add pagination to useOwnedNFTs (#1758) 2023-10-13 17:23:43 +00:00
fb0f12ae28 refactor(react): OTP Input Readability Enhancements (#1692)
Co-authored-by: Manan Tank <[email protected]>
2023-10-13 06:43:20 -07:00
91 changed files with 1510 additions and 508 deletions
+35
View File
@@ -1,5 +1,40 @@
# @thirdweb-dev/auth
## 4.0.7
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.0.7
## 4.0.6
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.0.6
## 4.0.5
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.0.5
## 4.0.4
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.0.4
## 4.0.3
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@2.0.3
## 4.0.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "4.0.2",
"version": "4.0.7",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/chains
## 0.1.55
### Patch Changes
- [#1783](https://github.com/thirdweb-dev/js/pull/1783) [`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64) Thanks [@jnsdls](https://github.com/jnsdls)! - sync chains
## 0.1.54
### Patch Changes
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 100,
"explorers": [
{
"name": "gnosisscan",
"url": "https://gnosisscan.io",
"name": "blockscout",
"url": "https://gnosis.blockscout.com",
"standard": "EIP3091"
},
{
"name": "blockscout",
"url": "https://gnosis.blockscout.com",
"name": "gnosisscan",
"url": "https://gnosisscan.io",
"standard": "EIP3091"
}
],
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 11110,
"explorers": [
{
"name": "Astra PingPub Explorer",
"url": "https://ping.astranaut.io/astra",
"name": "Astra EVM Explorer (Blockscout)",
"url": "https://explorer.astranaut.io",
"standard": "none"
},
{
"name": "Astra EVM Explorer (Blockscout)",
"url": "https://explorer.astranaut.io",
"name": "Astra PingPub Explorer",
"url": "https://ping.astranaut.io/astra",
"standard": "none"
}
],
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "Astra",
"chainId": 11115,
"explorers": [
{
"name": "Astra PingPub Explorer",
"url": "https://ping.astranaut.dev/astra",
"standard": "none"
},
{
"name": "Astra EVM Explorer",
"url": "https://explorer.astranaut.dev",
"standard": "EIP3091"
},
{
"name": "Astra PingPub Explorer",
"url": "https://ping.astranaut.dev/astra",
"standard": "none"
}
],
"faucets": [
-1
View File
@@ -19,7 +19,6 @@ export default {
},
"redFlags": [],
"rpc": [
"https://localhost.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"http://localhost:8545"
],
"shortName": "local",
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 2023,
"explorers": [
{
"name": "Taycan Cosmos Explorer",
"url": "https://cosmoscan-test.hupayx.io",
"name": "Taycan Explorer(Blockscout)",
"url": "https://evmscan-test.hupayx.io",
"standard": "none"
},
{
"name": "Taycan Explorer(Blockscout)",
"url": "https://evmscan-test.hupayx.io",
"name": "Taycan Cosmos Explorer",
"url": "https://cosmoscan-test.hupayx.io",
"standard": "none"
}
],
-1
View File
@@ -30,7 +30,6 @@ export default {
"rpc": [
"https://kava-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://evm.testnet.kava.io",
"https://kava-evm-testnet.rpc.thirdweb.com",
"wss://wevm.testnet.kava.io"
],
"shortName": "tkava",
-1
View File
@@ -30,7 +30,6 @@ export default {
"https://evm.kava.io",
"https://evm2.kava.io",
"https://kava-rpc.gateway.pokt.network",
"https://kava-evm.rpc.thirdweb.com",
"wss://wevm.kava.io",
"wss://wevm2.kava.io",
"https://kava-evm.publicnode.com",
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 30,
"explorers": [
{
"name": "Rootstock Explorer",
"url": "https://explorer.rsk.co",
"name": "blockscout",
"url": "https://rootstock.blockscout.com",
"standard": "EIP3091"
},
{
"name": "blockscout",
"url": "https://rootstock.blockscout.com",
"name": "Rootstock Explorer",
"url": "https://explorer.rsk.co",
"standard": "EIP3091"
}
],
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "SDN",
"chainId": 336,
"explorers": [
{
"name": "subscan",
"url": "https://shiden.subscan.io",
"standard": "none"
},
{
"name": "blockscout",
"url": "https://blockscout.com/shiden",
"standard": "EIP3091"
},
{
"name": "subscan",
"url": "https://shiden.subscan.io",
"standard": "none"
}
],
"faucets": [],
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 369,
"explorers": [
{
"name": "otterscan",
"url": "https://otter.pulsechain.com",
"name": "blockscout",
"url": "https://scan.pulsechain.com",
"standard": "EIP3091"
},
{
"name": "blockscout",
"url": "https://scan.pulsechain.com",
"name": "otterscan",
"url": "https://otter.pulsechain.com",
"standard": "EIP3091"
}
],
+3 -3
View File
@@ -18,7 +18,7 @@ export default {
"format": "png"
},
"infoURL": "http://doschain.io/",
"name": "DOS Tesnet",
"name": "DOS Testnet",
"nativeCurrency": {
"name": "DOS",
"symbol": "DOS",
@@ -26,10 +26,10 @@ export default {
},
"redFlags": [],
"rpc": [
"https://dos-tesnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://dos-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://test.doschain.com"
],
"shortName": "dost",
"slug": "dos-tesnet",
"slug": "dos-testnet",
"testnet": true
} as const satisfies Chain;
+1 -2
View File
@@ -27,8 +27,7 @@ export default {
"redFlags": [],
"rpc": [
"https://wireshape-floripa-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-floripa.wireshape.org",
"https://wireshape-floripa-testnet.rpc.thirdweb.com"
"https://rpc-floripa.wireshape.org"
],
"shortName": "floripa",
"slug": "wireshape-floripa-testnet",
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 50,
"explorers": [
{
"name": "blocksscan",
"url": "https://xdc.blocksscan.io",
"name": "xdcscan",
"url": "https://xdcscan.io",
"standard": "EIP3091"
},
{
"name": "xdcscan",
"url": "https://xdcscan.io",
"name": "blocksscan",
"url": "https://xdc.blocksscan.io",
"standard": "EIP3091"
}
],
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 51,
"explorers": [
{
"name": "blocksscan",
"url": "https://apothem.blocksscan.io",
"name": "xdcscan",
"url": "https://apothem.xinfinscan.com",
"standard": "EIP3091"
},
{
"name": "xdcscan",
"url": "https://apothem.xinfinscan.com",
"name": "blocksscan",
"url": "https://apothem.blocksscan.io",
"standard": "EIP3091"
}
],
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "Imversed",
"chainId": 5555555,
"explorers": [
{
"name": "Imversed Cosmos Explorer (Big Dipper)",
"url": "https://tex-c.imversed.com",
"standard": "none"
},
{
"name": "Imversed EVM explorer (Blockscout)",
"url": "https://txe.imversed.network",
"standard": "EIP3091"
},
{
"name": "Imversed Cosmos Explorer (Big Dipper)",
"url": "https://tex-c.imversed.com",
"standard": "none"
}
],
"faucets": [],
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "Imversed",
"chainId": 5555558,
"explorers": [
{
"name": "Imversed Cosmos Explorer (Big Dipper)",
"url": "https://tex-t.imversed.com",
"standard": "none"
},
{
"name": "Imversed EVM Explorer (Blockscout)",
"url": "https://txe-test.imversed.network",
"standard": "EIP3091"
},
{
"name": "Imversed Cosmos Explorer (Big Dipper)",
"url": "https://tex-t.imversed.com",
"standard": "none"
}
],
"faucets": [],
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 59140,
"explorers": [
{
"name": "Blockscout",
"url": "https://explorer.goerli.linea.build",
"name": "Etherscan",
"url": "https://goerli.lineascan.build",
"standard": "EIP3091"
},
{
"name": "Etherscan",
"url": "https://goerli.lineascan.build",
"name": "Blockscout",
"url": "https://explorer.goerli.linea.build",
"standard": "EIP3091"
}
],
-5
View File
@@ -7,11 +7,6 @@ export default {
"name": "lineascan",
"url": "https://lineascan.build",
"standard": "EIP3091"
},
{
"name": "Linea Scan",
"url": "https://lineascan.build",
"standard": ""
}
],
"faucets": [
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "ASTR",
"chainId": 592,
"explorers": [
{
"name": "subscan",
"url": "https://astar.subscan.io",
"standard": "none"
},
{
"name": "blockscout",
"url": "https://blockscout.com/astar",
"standard": "EIP3091"
},
{
"name": "subscan",
"url": "https://astar.subscan.io",
"standard": "none"
}
],
"faucets": [],
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 8000,
"explorers": [
{
"name": "Teleport Cosmos Explorer (Big Dipper)",
"url": "https://explorer.teleport.network",
"name": "Teleport EVM Explorer (Blockscout)",
"url": "https://evm-explorer.teleport.network",
"standard": "none"
},
{
"name": "Teleport EVM Explorer (Blockscout)",
"url": "https://evm-explorer.teleport.network",
"name": "Teleport Cosmos Explorer (Big Dipper)",
"url": "https://explorer.teleport.network",
"standard": "none"
}
],
+4 -4
View File
@@ -4,13 +4,13 @@ export default {
"chainId": 8001,
"explorers": [
{
"name": "Teleport Cosmos Explorer (Big Dipper)",
"url": "https://explorer.testnet.teleport.network",
"name": "Teleport EVM Explorer (Blockscout)",
"url": "https://evm-explorer.testnet.teleport.network",
"standard": "none"
},
{
"name": "Teleport EVM Explorer (Blockscout)",
"url": "https://evm-explorer.testnet.teleport.network",
"name": "Teleport Cosmos Explorer (Big Dipper)",
"url": "https://explorer.testnet.teleport.network",
"standard": "none"
}
],
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "ETH",
"chainId": 8453,
"explorers": [
{
"name": "basescan",
"url": "https://basescan.org",
"standard": "none"
},
{
"name": "basescout",
"url": "https://base.blockscout.com",
"standard": "EIP3091"
},
{
"name": "basescan",
"url": "https://basescan.org",
"standard": "none"
}
],
"faucets": [],
+5 -5
View File
@@ -3,15 +3,15 @@ export default {
"chain": "ETH",
"chainId": 84531,
"explorers": [
{
"name": "basescan",
"url": "https://goerli.basescan.org",
"standard": "none"
},
{
"name": "basescout",
"url": "https://base-goerli.blockscout.com",
"standard": "EIP3091"
},
{
"name": "basescan",
"url": "https://goerli.basescan.org",
"standard": "none"
}
],
"faucets": [
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.54",
"version": "0.1.55",
"main": "dist/thirdweb-dev-chains.cjs.js",
"module": "dist/thirdweb-dev-chains.esm.js",
"browser": {
+22 -24
View File
@@ -6,7 +6,7 @@ const BASE_URI = (process.env.BASE_URI as string) || "https://api.thirdweb.com";
async function getAllPaginatedChains(
chains: any[] = [],
pathname = "/v1/chains",
pathname = "/v1/chains?limit=100",
) {
const url = new URL(BASE_URI);
url.pathname = pathname;
@@ -33,31 +33,37 @@ async function sync() {
const results = await Promise.all(
allChainsInDB.map(async (chain) => {
let chainId = chain.chainId;
// try to convert to number for legacy reasons
try {
chainId = Number(chainId);
} catch {
// if we fail here then we cannot use this chain in the chains package for now, so we skip it
return null;
}
const pkgChain: Chain = {
...chain,
chainId: Number(chain.chainId),
// assing back the chainId
chainId,
// map the features to the legacy format
features: chain.features?.map((feature) => ({ name: feature })),
};
// remove all null values
Object.keys(pkgChain).forEach((key) => {
// @ts-ignore
if (pkgChain[key] === null || pkgChain[key] === undefined) {
// @ts-ignore
delete pkgChain[key];
}
});
// sort top level keys alphabetically
// @ts-ignore
const sortedChain: Chain = {};
const sortedChain = {} as Chain;
Object.keys(pkgChain)
.sort()
.forEach((key) => {
// @ts-ignore
sortedChain[key] = pkgChain[key];
});
// @ts-ignore
await fs.writeFile(
`${chainsDir}/${sortedChain.chainId}.ts`,
`import type { Chain } from "../src/types";
@@ -78,17 +84,8 @@ export default ${JSON.stringify(
exportName = `_${exportName}`;
}
// imports.push(`import c${chain.chainId} from "../chains/${chain.chainId}";`);
// exports.push(
// `export { default as ${exportName} } from "../chains/${chain.chainId}"`,
// );
const key = `c${sortedChain.chainId}`;
// exportNames.push(key);
// exportNameToChain[key] = chain;
return {
imp: `import c${sortedChain.chainId} from "../chains/${sortedChain.chainId}";`,
exp: `export { default as ${exportName} } from "../chains/${sortedChain.chainId}"`,
@@ -101,20 +98,21 @@ export default ${JSON.stringify(
const { imports, exports, exportNames, exportNameToChain } = results.reduce(
(acc, result) => {
// @ts-ignore
// if it's a null result skip it (can happen when we skip chains above because their chainID is out of bounds)
if (result === null) {
return acc;
}
acc.imports.push(result.imp);
// @ts-ignore
acc.exports.push(result.exp);
// @ts-ignore
acc.exportNames.push(result.key);
acc.exportNameToChain[result.key] = result.chain;
return acc;
},
{
imports: [],
exports: [],
exportNames: [],
exportNameToChain: {},
imports: [] as string[],
exports: [] as string[],
exportNames: [] as string[],
exportNameToChain: {} as Record<string, Chain>,
},
);
+2 -2
View File
@@ -1587,7 +1587,7 @@ export { default as Alveychain } from "../chains/3797"
export { default as Kalychain } from "../chains/3888"
export { default as KalychainTestnet } from "../chains/3889"
export { default as DracNetwork } from "../chains/3912"
export { default as DosTesnet } from "../chains/3939"
export { default as DosTestnet } from "../chains/3939"
export { default as Dyno } from "../chains/3966"
export { default as DynoTestnet } from "../chains/3967"
export { default as Yuanchain } from "../chains/3999"
@@ -3727,7 +3727,7 @@ type ChainIdsBySlug = {
"kalychain": 3888,
"kalychain-testnet": 3889,
"drac-network": 3912,
"dos-tesnet": 3939,
"dos-testnet": 3939,
"dyno": 3966,
"dyno-testnet": 3967,
"yuanchain": 3999,
+46
View File
@@ -1,5 +1,51 @@
# thirdweb
## 0.13.7
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
- @thirdweb-dev/sdk@4.0.6
- @thirdweb-dev/wallets@2.0.7
- @thirdweb-dev/auth@4.0.7
## 0.13.6
### Patch Changes
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
- @thirdweb-dev/sdk@4.0.5
- @thirdweb-dev/wallets@2.0.6
- @thirdweb-dev/auth@4.0.6
## 0.13.5
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.4
- @thirdweb-dev/wallets@2.0.5
- @thirdweb-dev/auth@4.0.5
## 0.13.4
### Patch Changes
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/sdk@4.0.3
- @thirdweb-dev/wallets@2.0.4
- @thirdweb-dev/auth@4.0.4
## 0.13.3
### Patch Changes
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
- @thirdweb-dev/sdk@4.0.2
- @thirdweb-dev/wallets@2.0.3
- @thirdweb-dev/auth@4.0.3
## 0.13.2
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.13.2",
"version": "0.13.7",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+12
View File
@@ -1,5 +1,17 @@
# @thirdweb-dev/contracts-js
## 1.3.16
### Patch Changes
- [#1771](https://github.com/thirdweb-dev/js/pull/1771) [`6c30b7ef`](https://github.com/thirdweb-dev/js/commit/6c30b7efc708e1244f3be3e10eac8f3b8b14a8c3) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Updated to latest contracts package
## 1.3.15
### Patch Changes
- [#1756](https://github.com/thirdweb-dev/js/pull/1756) [`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Enable adding smart wallet admins via bundler for new account contracts
## 1.3.14
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/contracts-js",
"version": "1.3.14",
"version": "1.3.16",
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
"module": "dist/thirdweb-dev-contracts-js.esm.js",
"browser": {
@@ -10,7 +10,7 @@
"license": "Apache-2.0",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
"dependencies": {
"@thirdweb-dev/contracts": "3.10.2-3"
"@thirdweb-dev/contracts": "3.10.3"
},
"devDependencies": {
"@babel/preset-env": "^7.22.9",
+48
View File
@@ -1,5 +1,53 @@
# @thirdweb-dev/react-core
## 4.0.7
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
- @thirdweb-dev/sdk@4.0.6
- @thirdweb-dev/wallets@2.0.7
- @thirdweb-dev/auth@4.0.7
## 4.0.6
### Patch Changes
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
- @thirdweb-dev/sdk@4.0.5
- @thirdweb-dev/wallets@2.0.6
- @thirdweb-dev/auth@4.0.6
## 4.0.5
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.4
- @thirdweb-dev/wallets@2.0.5
- @thirdweb-dev/auth@4.0.5
## 4.0.4
### Patch Changes
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/sdk@4.0.3
- @thirdweb-dev/wallets@2.0.4
- @thirdweb-dev/auth@4.0.4
## 4.0.3
### Patch Changes
- [#1758](https://github.com/thirdweb-dev/js/pull/1758) [`08e9cd20`](https://github.com/thirdweb-dev/js/commit/08e9cd206bcc37cf1e84a878dc78bc4f38e5092c) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Add pagination to useOwnedNFTs
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
- @thirdweb-dev/sdk@4.0.2
- @thirdweb-dev/wallets@2.0.3
- @thirdweb-dev/auth@4.0.3
## 4.0.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "4.0.2",
"version": "4.0.7",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -225,11 +225,12 @@ export function useTotalCirculatingSupply(
*
* @example
* ```javascript
* const { data: ownedNFTs, isLoading, error } = useOwnedNFTs(contract, "{{wallet_address}}");
* const { data: ownedNFTs, isLoading, error } = useOwnedNFTs(contract, "{{wallet_address}}", { start: 0, count: 100 });
* ```
*
* @param contract - an instance of a {@link NFTContract}
* @param ownerWalletAddress - the wallet address to get owned tokens for
* @param queryParams - query params to pass to the query for pagination
* @returns a response object that includes the list of owned tokens
* @beta
* @twfeature ERC721Enumerable | ERC1155Enumerable | ERC721Supply
@@ -238,6 +239,7 @@ export function useTotalCirculatingSupply(
export function useOwnedNFTs<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
ownerWalletAddress: RequiredParam<WalletAddress>,
queryParams?: QueryAllParams,
) {
const contractAddress = contract?.getAddress();
const { erc721, erc1155 } = getErcs(contract);
@@ -248,10 +250,10 @@ export function useOwnedNFTs<TContract extends NFTContract>(
requiredParamInvariant(contract, "No Contract instance provided");
invariant(ownerWalletAddress, "No wallet address provided");
if (erc721) {
return await erc721.getOwned(ownerWalletAddress);
return await erc721.getOwned(ownerWalletAddress, queryParams);
}
if (erc1155) {
return await erc1155.getOwned(ownerWalletAddress);
return await erc1155.getOwned(ownerWalletAddress, queryParams);
}
invariant(false, "Unknown NFT type");
},
+10
View File
@@ -1,5 +1,15 @@
# @thirdweb-dev/react-native-compat
## 0.3.12
## 0.3.11
## 0.3.10
## 0.3.9
## 0.3.8
## 0.3.7
## 0.3.6
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/react-native-compat",
"description": "Shims for Thirdweb in React Native Projects",
"version": "0.3.7",
"version": "0.3.12",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
"license": "Apache-2.0",
+70
View File
@@ -1,5 +1,75 @@
# @thirdweb-dev/react-native
## 0.3.12
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
- @thirdweb-dev/react-core@4.0.7
- @thirdweb-dev/sdk@4.0.6
- @thirdweb-dev/wallets@2.0.7
## 0.3.11
### Patch Changes
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
- @thirdweb-dev/sdk@4.0.5
- @thirdweb-dev/react-core@4.0.6
- @thirdweb-dev/wallets@2.0.6
## 0.3.10
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.4
- @thirdweb-dev/wallets@2.0.5
- @thirdweb-dev/react-core@4.0.5
## 0.3.9
### Patch Changes
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/sdk@4.0.3
- @thirdweb-dev/wallets@2.0.4
- @thirdweb-dev/react-core@4.0.4
## 0.3.8
### Patch Changes
- [#1724](https://github.com/thirdweb-dev/js/pull/1724) [`fc62b91e`](https://github.com/thirdweb-dev/js/commit/fc62b91ee55b0adba01298f33b21352004d1b71d) Thanks [@iketw](https://github.com/iketw)! - Adds Google sign in to embeddedWallet in React Native
You need to add the `react-native-inappbrowser-reborn` package to your app, then you can do:
```javascript
<ThirdwebProvider
activeChain={activeChain}
clientId={"your-client-id"}
supportedWallets={[
embeddedWallet({
// if this is true AND oauthOptions is not set we set it to false internally
email: true,
// if this is set we enable Sign in with Google
oauthOptions: {
redirectUrl: "test15app://",
providers: ["google"],
},
}),
]}
>
<App />
</ThirdwebProvider>
```
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`08e9cd20`](https://github.com/thirdweb-dev/js/commit/08e9cd206bcc37cf1e84a878dc78bc4f38e5092c), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.3.7
### Patch Changes
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.3.7",
"version": "0.3.12",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -89,7 +89,8 @@
"amazon-cognito-identity-js": "^6.3.3",
"react-native-quick-base64": "^2.0.7",
"react-native-quick-crypto": "^0.6.1",
"react-native-aes-gcm-crypto": "^0.2.2"
"react-native-aes-gcm-crypto": "^0.2.2",
"react-native-inappbrowser-reborn": "^3.7.0"
},
"peerDependencies": {
"ethers": ">=5.5.1 <6",
@@ -10,3 +10,4 @@ export * from "./right-arrow";
export * from "./wallet";
export * from "./money";
export * from "./switch";
export * from "./svgs";
@@ -1,3 +1,23 @@
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"
fill="#4285F4"
/>
<path
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
fill="#34A853"
/>
<path
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
fill="#FBBC05"
/>
<path
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
fill="#EA4335"
/>
<path d="M1 1h22v22H1z" fill="none" />
</svg>`;
export const EMAIL_WALLET_ICON = `<svg width="48" height="48" viewBox="0 0 48 48" fill="none">
<g clip-path="url(#clip0_3589_8649)">
<rect width="48" height="48" rx="8" fill="url(#paint0_linear_3589_8649)"/>
@@ -238,7 +238,8 @@ export const ConnectWalletDetailsModal = ({
) : null}
</BaseButton>
) : null}
{activeWallet?.walletId === EmbeddedWallet.id ? (
{activeWallet?.walletId === EmbeddedWallet.id &&
(activeWallet as EmbeddedWallet).getEmail() ? (
<Box flexDirection="row" alignItems="center" mt="md">
<ActiveDot width={10} height={10} />
<Text variant="bodySmallSecondary" ml="xxs">
@@ -246,7 +247,11 @@ export const ConnectWalletDetailsModal = ({
</Text>
</Box>
) : null}
<Box flexDirection="row" justifyContent="space-evenly" mt="md">
<Box
flexDirection="row"
justifyContent="space-evenly"
marginVertical="md"
>
<SendButton supportedTokens={supportedTokens} />
<ReceiveButton />
</Box>
@@ -330,7 +335,6 @@ const styles = StyleSheet.create({
alignContent: "flex-start",
alignItems: "flex-start",
justifyContent: "flex-start",
marginTop: 24,
marginBottom: 8,
},
});
@@ -1,7 +1,6 @@
import { AddressDisplay } from "../base/AddressDisplay";
import BaseButton from "../base/BaseButton";
import Text from "../base/Text";
import { WalletIcon } from "../base/WalletIcon";
import { useENS, useWallet } from "@thirdweb-dev/react-core";
import { StyleSheet } from "react-native";
import { LocalWallet, walletIds } from "@thirdweb-dev/wallets";
@@ -11,6 +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";
export type ConnectWalletDetailsProps = {
address?: string;
@@ -90,7 +90,13 @@ export const WalletDetailsButton = ({
alignContent="center"
justifyContent="flex-start"
>
<WalletIcon size={32} iconUri={avatarUrl || walletIconUrl} />
<Box borderRadius="lg" overflow="hidden">
<ImageSvgUri
width={32}
height={32}
imageUrl={avatarUrl || walletIconUrl}
/>
</Box>
<Box ml="md" justifyContent="center" alignItems="flex-start">
{activeWallet?.walletId === LocalWallet.id ? (
<Text variant="bodySmall" color="red">
@@ -261,9 +261,7 @@ export function ChooseWallet({
) : null}
{showToSPrivacyPolicy ? (
<Box
mt="md"
pt="md"
height={50}
mt="sm"
marginHorizontal={!isConnectAWalletEnabled ? "xl" : "none"}
alignItems="center"
>
@@ -62,8 +62,8 @@ export const ConnectWalletFlow = () => {
const onChooseWallet = useCallback(
(wallet: WalletConfig, data?: any) => {
setActiveWallet(wallet);
setSelectionData(data);
setActiveWallet(wallet);
// If the wallet has no custom connect UI, then connect it
if (!wallet.connectUI) {
@@ -30,7 +30,7 @@ export function ConnectingWallet({
subHeaderText={subHeaderText}
onClose={onClose}
/>
<WalletLoadingThumbnail imageSize={100}>
<WalletLoadingThumbnail imageSize={85}>
<ImageSvgUri height={80} width={80} imageUrl={wallet.meta.iconURL} />
</WalletLoadingThumbnail>
<View style={styles.connectingContainer}>
@@ -131,7 +131,7 @@ export const SmartWalletFlow = ({
onBackPress={onConnectingBackPress}
onClose={onConnectingClosePress}
/>
<WalletLoadingThumbnail imageSize={100}>
<WalletLoadingThumbnail imageSize={85}>
<ImageSvgUri
height={80}
width={80}
@@ -12,7 +12,7 @@ import { TWModal } from "./base/modal/TWModal";
import Box from "./base/Box";
// import { useAppTheme } from "../styles/hooks";
const MODAL_HEIGHT = Dimensions.get("window").height * 0.6;
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
const DEVICE_WIDTH = Dimensions.get("window").width;
export const MainModal = () => {
@@ -144,7 +144,7 @@ const SendFundsForm = ({
const wallet = useWallet();
const chainId = useChainId();
const [receiverAddress, setReceiverAddress] = useState("");
const [amount, setAmount] = useState("");
const [amount, setAmount] = useState("0");
const [showIcon, setShowIcon] = useState(false);
const tokenAddress = token?.address;
@@ -313,6 +313,7 @@ const SendFundsForm = ({
editable={!sendTokenMutation.isLoading}
returnKeyType={"done"}
keyboardType="numeric"
value={amount}
clearTextOnFocus={false}
style={{
color: theme.colors.textPrimary,
@@ -322,8 +323,6 @@ const SendFundsForm = ({
paddingHorizontal: 16,
}}
onChangeText={setAmount}
placeholder="0"
placeholderTextColor={theme.colors.textPrimary}
autoCapitalize="none"
autoCorrect={false}
/>
@@ -348,9 +347,16 @@ const SendFundsForm = ({
}}
>
{sendTokenMutation.isLoading ? (
<ActivityIndicator size="small" color={theme.colors.textPrimary} />
<ActivityIndicator
size="small"
color={theme.colors.accentButtonTextColor}
/>
) : showIcon ? (
<CheckIcon width={20} height={13} color={theme.colors.textPrimary} />
<CheckIcon
width={20}
height={13}
color={theme.colors.accentButtonTextColor}
/>
) : (
<Text variant="bodySmall" color="accentButtonTextColor" mr="sm">
Send
@@ -35,7 +35,7 @@ const ImageSvgUri = ({
}
return (
<Box style={{ width: width, height: height }}>
<Box width={width} height={height}>
{error ? (
<SvgUri width={width} height={height} uri={resolvedImageUrl} />
) : (
@@ -72,6 +72,7 @@ export const NetworkButton = ({
<>
<BaseButton
p={padding || "sm"}
paddingVertical="xs"
borderRadius="md"
borderWidth={0.5}
flexDirection="row"
@@ -82,13 +83,8 @@ export const NetworkButton = ({
{...props}
>
<Box flexDirection="row" alignItems="center">
<ChainIcon chainIconUrl={chain?.icon?.url} size={32} />
<Box
ml="md"
alignItems="flex-start"
justifyContent="center"
height={36}
>
<ChainIcon chainIconUrl={chain?.icon?.url} size={28} />
<Box ml="md" alignItems="flex-start" justifyContent="center">
<Text variant="bodyLarge">{chain?.name || "Unknown Network"}</Text>
{isSwitching ? (
<Box flexDirection="row" alignItems="center">
@@ -4,20 +4,27 @@ import ImageSvgUri from "./ImageSvgUri";
import { Label } from "./Label";
import Text from "./Text";
import Box from "./Box";
import { Palette } from "../../styles/colors";
type WalletButtonProps = {
onPress?: () => void;
walletIconUrl: string;
name: string;
nameColor?: keyof Palette;
labelText?: string;
recommended?: boolean;
iconWidth?: number;
iconHeight?: number;
} & React.ComponentProps<typeof BaseButton>;
export const WalletButton = ({
iconWidth = 48,
iconHeight = 48,
mb,
onPress,
walletIconUrl,
name,
nameColor = "textPrimary",
labelText,
recommended,
...props
@@ -36,9 +43,15 @@ export const WalletButton = ({
{...props}
>
<Box flexDirection="row" justifyContent="flex-start" alignItems="center">
<ImageSvgUri imageUrl={walletIconUrl} width={48} height={48} />
<ImageSvgUri
imageUrl={walletIconUrl}
width={iconWidth}
height={iconHeight}
/>
<Box ml="sm" alignItems="flex-start">
<Text variant="bodyLarge">{name}</Text>
<Text variant="bodyLarge" color={nameColor}>
{name}
</Text>
{recommended ? <Text variant="link">Recommended</Text> : null}
</Box>
</Box>
@@ -1,12 +1,13 @@
import {
EmbeddedWalletConnectionArgs,
EmbeddedWalletConnectorOptions,
OauthOption,
} 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 { sendEmailOTP, validateEmailOTP } from "./embedded/auth";
import { sendEmailOTP, socialLogin, validateEmailOTP } from "./embedded/auth";
import { getEthersSigner } from "./embedded/signer";
import { logoutUser } from "./embedded/helpers/auth/logout";
import {
@@ -83,6 +84,36 @@ export class EmbeddedWalletConnector extends Connector<EmbeddedWalletConnectionA
return sendEmailOTP(email, this.options.clientId);
}
async socialLogin(oauthOption: OauthOption) {
try {
const { email } = await socialLogin(oauthOption, this.options.clientId);
this.email = email;
saveConnectedEmail(email);
} catch (error) {
console.error(
`Error while signing in with: ${oauthOption.provider}. ${error}`,
);
if (error instanceof Error) {
return { error: error.message };
} else {
return { error: "An unknown error occurred" };
}
}
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> {
clearConnectedEmail();
await logoutUser(this.options.clientId);
@@ -19,6 +19,9 @@ import { postPaperAuth, 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 { OauthOption } from "../types";
import { ROUTE_HEADLESS_GOOGLE_LOGIN } from "./helpers/constants";
export async function sendEmailOTP(
email: string,
@@ -122,3 +125,74 @@ export async function validateEmailOTP({
);
}
}
export async function socialLogin(oauthOptions: OauthOption, clientId: string) {
const headlessLoginLinkWithParams = `${ROUTE_HEADLESS_GOOGLE_LOGIN}?authProvider=${encodeURIComponent(
"google",
)}&baseUrl=${encodeURIComponent(
"https://ews.thirdweb.com",
)}&platform=${encodeURIComponent("mobile")}`;
const resp = await fetch(headlessLoginLinkWithParams);
if (!resp.ok) {
throw new Error("Error getting headless login link");
}
const json = await resp.json();
const { platformLoginLink } = json;
const completeLoginUrl = `${platformLoginLink}?developerClientId=${encodeURIComponent(
clientId || "",
)}&platform=${encodeURIComponent("mobile")}&redirectUrl=${encodeURIComponent(
oauthOptions.redirectUrl,
)}`;
const result = await InAppBrowser.openAuth(
completeLoginUrl,
oauthOptions.redirectUrl,
{
// iOS Properties
ephemeralWebSession: false,
// Android Properties
showTitle: false,
enableUrlBarHiding: false,
enableDefaultShare: false,
},
);
if (result.type !== "success") {
throw new Error("Error signing in. Please try again later.");
}
const decodedUrl = decodeURIComponent(result.url);
const parts = decodedUrl.split("?authResult=");
if (parts.length < 2) {
throw new Error("Malformed response from the login redirect");
}
const authResult = parts[1];
const { storedToken } = JSON.parse(authResult);
try {
const toStoreToken: AuthStoredTokenWithCookieReturnType["storedToken"] = {
jwtToken: storedToken.jwtToken,
authDetails: storedToken.authDetails,
authProvider: storedToken.authProvider,
developerClientId: storedToken.developerClientId,
cookieString: storedToken.cookieString,
// we should always store the jwt cookie since there's no concept of cookie in react native
shouldStoreCookieString: true,
isNewUser: storedToken.isNewUser,
};
await postPaperAuth(toStoreToken, clientId);
return { storedToken, email: storedToken.authDetails.email };
} catch (e) {
throw new Error(
`Malformed response from post authentication: ${JSON.stringify(e)}`,
);
}
}
@@ -30,4 +30,6 @@ export const ROUTE_STORE_USER_SHARES = `${ROUTE_2022_08_12_API_BASE_PATH}/embedd
export const ROUTE_GET_USER_SHARES = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/get-shares`;
export const ROUTE_VERIFY_THIRDWEB_CLIENT_ID = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/verify-thirdweb-client-id`;
export const ROUTE_HEADLESS_GOOGLE_LOGIN = `${BASE_URL}/api/2022-08-12/embedded-wallet/headless-login-link`;
export const ROUTE_AUTH_COGNITO_ID_TOKEN = `${ROUTE_2022_08_12_API_BASE_PATH}/embedded-wallet/cognito-id-token`;
@@ -1,11 +1,21 @@
import { Chain } from "@thirdweb-dev/chains";
import { WalletOptions } from "@thirdweb-dev/wallets";
import type {
RecoveryShareManagement,
PaperConstructorType,
AuthProvider,
} from "@paperxyz/embedded-wallet-service-sdk";
export type OauthOptions = {
providers: AuthProvider[];
redirectUrl: string;
};
export type OauthOption = {
provider: AuthProvider;
redirectUrl: string;
};
export interface EmbeddedConnectorOptions {
chains?: Chain[];
chainId?: number;
@@ -17,6 +17,8 @@ import Box from "../../../components/base/Box";
import Text from "../../../components/base/Text";
import BaseButton from "../../../components/base/BaseButton";
import * as Clipboard from "expo-clipboard";
import { StyleSheet } from "react-native";
import { EmbeddedSocialConnection } from "./EmbeddedSocialConnection";
import { useGlobalTheme } from "../../../providers/ui-context-provider";
const OTP_LENGTH = 6;
@@ -26,6 +28,7 @@ export const EmbeddedConnectionUI: React.FC<ConnectUIProps<EmbeddedWallet>> = ({
goBack,
selectionData,
onLocallyConnected,
...props
}) => {
const theme = useGlobalTheme();
const inputRefs = useRef<(TextInput | null)[]>([]);
@@ -104,6 +107,7 @@ export const EmbeddedConnectionUI: React.FC<ConnectUIProps<EmbeddedWallet>> = ({
inputRefs.current[i]?.setNativeProps({ text: newValues[i] });
}
setValues(newValues);
Clipboard.setStringAsync("");
return;
}
}
@@ -157,6 +161,18 @@ export const EmbeddedConnectionUI: React.FC<ConnectUIProps<EmbeddedWallet>> = ({
});
};
if (selectionData?.oauthOptions) {
return (
<EmbeddedSocialConnection
connected={() => {}}
goBack={goBack}
onLocallyConnected={onLocallyConnected}
selectionData={selectionData}
{...props}
/>
);
}
return (
<Box marginHorizontal="xl">
<ConnectWalletHeader
@@ -198,10 +214,8 @@ export const EmbeddedConnectionUI: React.FC<ConnectUIProps<EmbeddedWallet>> = ({
<TextInput
ref={(ref) => (inputRefs.current[index] = ref)}
style={{
fontSize: 20,
...styles.textInput,
color: theme.colors.textPrimary,
textAlign: "center",
height: 50,
}}
keyboardType="number-pad"
editable={!checkingOtp}
@@ -246,3 +260,11 @@ export const EmbeddedConnectionUI: React.FC<ConnectUIProps<EmbeddedWallet>> = ({
</Box>
);
};
const styles = StyleSheet.create({
textInput: {
fontSize: 20,
textAlign: "center",
height: 50,
},
});
@@ -9,22 +9,30 @@ import Box from "../../../components/base/Box";
import Text from "../../../components/base/Text";
import BaseButton from "../../../components/base/BaseButton";
import { TextInput } from "../../../components/base/TextInput";
import { GOOGLE_ICON } from "../../../assets/svgs";
import { WalletButton } from "../../../components/base/WalletButton";
import { AuthProvider } from "@paperxyz/embedded-wallet-service-sdk";
import { OauthOptions } from "../../connectors/embedded-wallet/types";
import { useGlobalTheme } from "../../../providers/ui-context-provider";
/**
* UI for selecting wallet - this UI is rendered in the wallet selection screen
*/
export const EmailSelectionUI: React.FC<SelectUIProps<EmbeddedWallet>> = ({
onSelect,
walletConfig,
}) => {
export const EmailSelectionUI: React.FC<
SelectUIProps<EmbeddedWallet> & {
oauthOptions?: OauthOptions;
email?: boolean;
}
> = ({ onSelect, walletConfig, oauthOptions, email }) => {
const theme = useGlobalTheme();
const [email, setEmail] = useState<string>("");
const [emailInput, setEmailInput] = useState<string>("");
const [errorMessage, setErrorMessage] = useState<string>("");
const [isFetching, setIsFetching] = useState<boolean>(false);
const createWalletInstance = useCreateWalletInstance();
const [emailWallet, setEmailWallet] = useState<EmbeddedWallet | null>(null);
const isEmailEnabled = email === false ? false : true;
useEffect(() => {
const emailWalletInstance = createWalletInstance(
walletConfig,
@@ -39,17 +47,18 @@ export const EmailSelectionUI: React.FC<SelectUIProps<EmbeddedWallet>> = ({
};
const handleNetworkCall = () => {
if (validateEmail(email)) {
if (validateEmail(emailInput)) {
setErrorMessage("");
setIsFetching(true);
emailWallet
?.sendEmailOTP(email)
?.sendEmailOTP(emailInput)
.then((response) => {
onSelect({
...response,
email,
email: emailInput,
emailWallet,
oauthOptions: undefined,
});
})
.catch((error) => {
@@ -65,58 +74,109 @@ export const EmailSelectionUI: React.FC<SelectUIProps<EmbeddedWallet>> = ({
}
};
const onGoogleSignInPress = () => {
onSelect({
email: emailInput,
emailWallet,
oauthOptions: {
provider: oauthOptions?.providers[0],
redirectUrl: oauthOptions?.redirectUrl,
},
});
};
return (
<Box paddingHorizontal="xl" mt="lg">
<TextInput
textInputProps={{
placeholder: "Enter your email address",
placeholderTextColor: theme.colors.textSecondary,
onChangeText: setEmail,
style: {
fontSize: 14,
color: theme.colors.textPrimary,
lineHeight: 16,
padding: 0,
flex: 1,
},
value: email,
keyboardType: "email-address",
returnKeyType: "done",
autoCapitalize: "none",
autoCorrect: false,
autoComplete: "off",
clearTextOnFocus: false,
}}
containerProps={{
paddingHorizontal: "sm",
paddingVertical: "sm",
justifyContent: "flex-start",
}}
/>
<BaseButton
mt="md"
paddingVertical="md"
borderRadius="lg"
borderWidth={1}
borderColor="border"
backgroundColor="accentButtonColor"
onPress={handleNetworkCall}
>
{isFetching ? (
<ActivityIndicator
size={"small"}
color={theme.colors.accentButtonTextColor}
{oauthOptions?.providers.includes(AuthProvider.GOOGLE) ? (
<Box justifyContent="center">
<WalletButton
iconHeight={28}
iconWidth={28}
borderRadius="lg"
borderWidth={1}
borderColor="buttonBackgroundColor"
backgroundColor="buttonBackgroundColor"
nameColor="buttonTextColor"
justifyContent="center"
name="Sign in with Google"
walletIconUrl={GOOGLE_ICON}
onPress={onGoogleSignInPress}
/>
) : (
<Text
variant="bodySmall"
color="accentButtonTextColor"
fontWeight="700"
{isEmailEnabled ? (
<Box
mb="md"
mt="md"
flexDirection="row"
justifyContent="center"
alignItems="center"
>
<Box height={1} flex={1} backgroundColor="border" />
<Text
variant="subHeader"
textAlign="center"
marginHorizontal="xxs"
>
OR
</Text>
<Box height={1} flex={1} backgroundColor="border" />
</Box>
) : null}
</Box>
) : null}
{isEmailEnabled ? (
<>
<TextInput
textInputProps={{
placeholder: "Enter your email address",
placeholderTextColor: theme.colors.textSecondary,
onChangeText: setEmailInput,
style: {
fontSize: 14,
color: theme.colors.textPrimary,
lineHeight: 16,
padding: 0,
flex: 1,
},
value: emailInput,
keyboardType: "email-address",
returnKeyType: "done",
autoCapitalize: "none",
autoCorrect: false,
autoComplete: "off",
clearTextOnFocus: false,
}}
containerProps={{
paddingHorizontal: "sm",
paddingVertical: "sm",
justifyContent: "flex-start",
}}
/>
<BaseButton
mt="md"
paddingVertical="md"
borderRadius="lg"
borderWidth={1}
borderColor="border"
backgroundColor="accentButtonColor"
onPress={handleNetworkCall}
>
Continue
</Text>
)}
</BaseButton>
{isFetching ? (
<ActivityIndicator
size={"small"}
color={theme.colors.accentButtonTextColor}
/>
) : (
<Text
variant="bodySmall"
color="accentButtonTextColor"
fontWeight="700"
>
Continue
</Text>
)}
</BaseButton>
</>
) : null}
{errorMessage ? (
<Text variant="error" mt="xxs">
{errorMessage}
@@ -0,0 +1,86 @@
import { useCallback, useEffect, useState } from "react";
import React from "react";
import { ActivityIndicator } from "react-native";
import { EmbeddedWallet } from "./EmbeddedWallet";
import {
ConnectUIProps,
useSetConnectedWallet,
useSetConnectionStatus,
} from "@thirdweb-dev/react-core";
import { GOOGLE_ICON } from "../../../assets";
import { ConnectWalletHeader } from "../../../components/ConnectWalletFlow/ConnectingWallet/ConnectingWalletHeader";
import { Box, Text, WalletButton } from "../../../components/base";
export const EmbeddedSocialConnection: React.FC<
ConnectUIProps<EmbeddedWallet>
> = ({ goBack, selectionData, onLocallyConnected }) => {
const setConnectedWallet = useSetConnectedWallet();
const setConnectionStatus = useSetConnectionStatus();
const [errorMessage, setErrorMessage] = useState<string>();
const handleGoogleLogin = useCallback(() => {
setErrorMessage("");
setTimeout(() => {
(selectionData.emailWallet as EmbeddedWallet)
.socialLogin(selectionData?.oauthOptions)
.then(async (response) => {
if (response?.success) {
if (onLocallyConnected) {
onLocallyConnected(selectionData.emailWallet);
} else {
await setConnectedWallet(selectionData.emailWallet);
setConnectionStatus("connected");
}
} else {
setErrorMessage(
response?.error || "Error login in. Please try again later.",
);
}
})
.catch((error) => {
console.error("Error validating otp: ", error);
setErrorMessage("Error login in. Please try again later.");
});
}, 0);
}, [
onLocallyConnected,
selectionData.emailWallet,
selectionData.oauthOptions,
setConnectedWallet,
setConnectionStatus,
]);
useEffect(() => {
handleGoogleLogin();
}, [handleGoogleLogin]);
return (
<Box marginHorizontal="xl" height={200}>
<ConnectWalletHeader
middleContent={
<WalletButton
iconHeight={28}
iconWidth={28}
borderRadius="lg"
justifyContent="center"
name="Sign In"
walletIconUrl={GOOGLE_ICON}
/>
}
subHeaderText={""}
onBackPress={goBack}
onClose={goBack}
/>
<Box flex={1} justifyContent="center" alignItems="center">
{!errorMessage ? (
<ActivityIndicator size="large" />
) : (
<Text variant="error" numberOfLines={1}>
{errorMessage}
</Text>
)}
</Box>
</Box>
);
};
@@ -5,7 +5,10 @@ import {
walletIds,
} from "@thirdweb-dev/wallets";
import type { EmbeddedWalletConnector as EmbeddedConnectorType } from "../../connectors/embedded-wallet/embedded-connector";
import { EmbeddedWalletConnectionArgs } from "../../connectors/embedded-wallet/types";
import {
EmbeddedWalletConnectionArgs,
OauthOption,
} from "../../connectors/embedded-wallet/types";
import { EmbeddedWalletConnector } from "../../connectors/embedded-wallet/embedded-connector";
import { EMAIL_WALLET_ICON } from "../../../assets/svgs";
@@ -43,8 +46,6 @@ export class EmbeddedWallet extends AbstractClientWallet<
return this.connector;
}
// my methods
initializeConnector() {
this.connector = new EmbeddedWalletConnector({
...this.options,
@@ -63,6 +64,10 @@ export class EmbeddedWallet extends AbstractClientWallet<
return this.connector?.sendEmailOtp(email);
}
async socialLogin(oauthOption: OauthOption) {
return this.connector?.socialLogin(oauthOption);
}
onConnected = () => {
this.emit("message", { type: "connected" });
};
@@ -6,16 +6,40 @@ import {
} from "@thirdweb-dev/react-core";
import { EmbeddedConnectionUI } from "./EmbeddedConnectionUI";
import { EmailSelectionUI } from "./EmbeddedSelectionUI";
import { AuthProvider } from "@paperxyz/embedded-wallet-service-sdk";
type OAuthProvider = "google"; // currently we only have one
export type EmbeddedWalletConfig = {
recommended?: boolean;
// @default true - set false to disable
email?: boolean;
// @default { providers: ['google'] } - set false to disable
oauthOptions?:
| {
providers: OAuthProvider[];
redirectUrl: string;
}
| false;
};
export const embeddedWallet = (
config?: EmbeddedWalletConfig,
): WalletConfig<EmbeddedWallet> => {
const selectUI = (props: SelectUIProps<EmbeddedWallet>) => (
<EmailSelectionUI {...props} />
<EmailSelectionUI
{...props}
oauthOptions={
config?.oauthOptions
? {
providers: [AuthProvider.GOOGLE],
redirectUrl: config.oauthOptions.redirectUrl,
}
: undefined
}
// you cannot disable both email and oauth
email={!config?.oauthOptions && !config?.email ? true : config?.email}
/>
);
return {
@@ -29,6 +53,5 @@ export const embeddedWallet = (
},
selectUI: selectUI,
connectUI: EmbeddedConnectionUI,
recommended: config?.recommended,
};
};
+52
View File
@@ -1,5 +1,57 @@
# @thirdweb-dev/react
## 4.0.7
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
- @thirdweb-dev/react-core@4.0.7
- @thirdweb-dev/sdk@4.0.6
- @thirdweb-dev/wallets@2.0.7
## 4.0.6
### Patch Changes
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
- @thirdweb-dev/sdk@4.0.5
- @thirdweb-dev/react-core@4.0.6
- @thirdweb-dev/wallets@2.0.6
## 4.0.5
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.4
- @thirdweb-dev/wallets@2.0.5
- @thirdweb-dev/react-core@4.0.5
## 4.0.4
### Patch Changes
- [#1769](https://github.com/thirdweb-dev/js/pull/1769) [`010955ff`](https://github.com/thirdweb-dev/js/commit/010955ff5cc35a975b54c25992b8e65b40e033a1) Thanks [@MananTank](https://github.com/MananTank)! - Fix OTP input not working well with Japanese keyboard
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/sdk@4.0.3
- @thirdweb-dev/wallets@2.0.4
- @thirdweb-dev/react-core@4.0.4
## 4.0.3
### Patch Changes
- [#1766](https://github.com/thirdweb-dev/js/pull/1766) [`dd7d0fca`](https://github.com/thirdweb-dev/js/commit/dd7d0fca2d14a529343396a31939d49b1a074d3e) Thanks [@MananTank](https://github.com/MananTank)! - Fix Continue as Guest button missing when Social + Guest login is setup in ConnectWallet Modal
- [#1692](https://github.com/thirdweb-dev/js/pull/1692) [`fb0f12ae`](https://github.com/thirdweb-dev/js/commit/fb0f12ae2835f4eba60ba4a74b453151cab0d393) Thanks [@etnlbck](https://github.com/etnlbck)! - Refactored OTPInput component to be simpler to read
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`08e9cd20`](https://github.com/thirdweb-dev/js/commit/08e9cd206bcc37cf1e84a878dc78bc4f38e5092c), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
- @thirdweb-dev/sdk@4.0.2
- @thirdweb-dev/react-core@4.0.3
- @thirdweb-dev/wallets@2.0.3
## 4.0.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "4.0.2",
"version": "4.0.7",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+5 -3
View File
@@ -36,15 +36,17 @@ export function OTPInput(props: {
data-error={props.isInvalid}
ref={(e) => (boxEls.current[i] = e)}
key={i}
value={otp[i] === undefined ? "" : otp[i]}
value={otp[i] ?? ""}
type="number"
pattern="[0-9]*"
variant="outline"
inputMode="numeric"
onPaste={(e) => {
const pastedData = e.clipboardData.getData("text/plain");
const newOTP = pastedData
.slice(0, props.digits)
.split("")
.filter((n) => /[0-9]/.test(n))
.filter((n) => /\d/.test(n))
.map(Number);
setOTP(newOTP);
@@ -100,7 +102,7 @@ export function OTPInput(props: {
}
}
if (!/[0-9]/.test(value) && value !== "") {
if (!/\d/.test(value) && value !== "") {
e.preventDefault();
return;
}
@@ -255,18 +255,19 @@ export const WalletSelector: React.FC<{
// only social login - no eoa wallets
if (eoaWallets.length === 0) {
bottomSection = tos ? (
<>
<Spacer y="md" />
<Line />
{continueAsGuest && (
<Container p="lg"> {continueAsGuest}</Container>
)}
{tos && <Container p="md"> {tos} </Container>}
</>
) : (
<Spacer y="sm" />
);
bottomSection =
tos || continueAsGuest ? (
<>
<Spacer y="md" />
<Line />
{continueAsGuest && (
<Container p="lg"> {continueAsGuest}</Container>
)}
{tos && <Container p="md"> {tos} </Container>}
</>
) : (
<Spacer y="sm" />
);
}
// social login + eoa wallets
+41
View File
@@ -1,5 +1,46 @@
# @thirdweb-dev/sdk
## 4.0.6
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
## 4.0.5
### Patch Changes
- [#1781](https://github.com/thirdweb-dev/js/pull/1781) [`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose utility functions for fetching ABI / sources
## 4.0.4
### Patch Changes
- Updated dependencies [[`6c30b7ef`](https://github.com/thirdweb-dev/js/commit/6c30b7efc708e1244f3be3e10eac8f3b8b14a8c3)]:
- @thirdweb-dev/contracts-js@1.3.16
## 4.0.3
### Patch Changes
- [#1756](https://github.com/thirdweb-dev/js/pull/1756) [`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Enable adding smart wallet admins via bundler for new account contracts
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/contracts-js@1.3.15
## 4.0.2
### Patch Changes
- [#1764](https://github.com/thirdweb-dev/js/pull/1764) [`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Perf improvement for marketplace methods
- [#1763](https://github.com/thirdweb-dev/js/pull/1763) [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Improve fetchPublishedContractFromPolygon
- [#1765](https://github.com/thirdweb-dev/js/pull/1765) [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Perf improvement for getting deployment info
- [#1762](https://github.com/thirdweb-dev/js/pull/1762) [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Perf improvement for drop-claim-condition
## 4.0.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "4.0.1",
"version": "4.0.6",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
@@ -50,18 +50,18 @@ export async function fetchPublishedContractFromPolygon(
});
// get the metadata for each version
const versionMetadata = await Promise.all(
allVersions.map(async (c) => {
return {
name: c.id,
publishedTimestamp: c.timestamp,
publishedMetadata: await fetchAndCacheDeployMetadata(
c.metadataUri,
storage,
),
};
}),
);
const versionMetadata = (
await Promise.all(
allVersions.map((c) =>
fetchAndCacheDeployMetadata(c.metadataUri, storage),
),
)
).map((item, index) => ({
name: allVersions[index].id,
publishedTimestamp: allVersions[index].timestamp,
publishedMetadata: item,
}));
// find the version that matches the version string
const versionMatch = versionMetadata.find(
(metadata) =>
@@ -37,15 +37,13 @@ export async function getDeploymentInfo(
secretKey?: string,
): Promise<DeploymentPreset[]> {
caches.deploymentPresets = {};
const create2FactoryAddress = create2Factory
? create2Factory
: await getCreate2FactoryAddress(provider);
const [create2FactoryAddress, { compilerMetadata, extendedMetadata }] =
await Promise.all([
create2Factory ? create2Factory : getCreate2FactoryAddress(provider),
fetchAndCacheDeployMetadata(metadataUri, storage),
]);
const customParams: ConstructorParamMap = {};
const finalDeploymentInfo: DeploymentPreset[] = [];
const { compilerMetadata, extendedMetadata } =
await fetchAndCacheDeployMetadata(metadataUri, storage);
const defaultExtensions = extendedMetadata?.defaultExtensions;
if (extendedMetadata?.routerType === "plugin" && defaultExtensions) {
@@ -65,16 +63,16 @@ export async function getDeploymentInfo(
const pluginMetadata = (
await Promise.all(
publishedExtensions.map(async (c) => {
return fetchAndCacheDeployMetadata(c.metadataUri, storage);
}),
publishedExtensions.map((c) =>
fetchAndCacheDeployMetadata(c.metadataUri, storage),
),
)
).map((fetchedMetadata) => fetchedMetadata.compilerMetadata);
// get deployment info for all plugins
const pluginDeploymentInfo = await Promise.all(
pluginMetadata.map(async (metadata) => {
const info = await computeDeploymentInfo(
pluginMetadata.map((metadata) =>
computeDeploymentInfo(
"plugin",
provider,
storage,
@@ -82,9 +80,8 @@ export async function getDeploymentInfo(
{ metadata: metadata },
clientId,
secretKey,
);
return info;
}),
),
),
);
// create constructor param input for PluginMap
@@ -142,8 +139,8 @@ export async function getDeploymentInfo(
// get deployment info for all extensions
const extensionDeploymentInfo = await Promise.all(
extensionMetadata.map(async (metadata) => {
const info = await computeDeploymentInfo(
extensionMetadata.map((metadata) =>
computeDeploymentInfo(
"extension",
provider,
storage,
@@ -151,9 +148,8 @@ export async function getDeploymentInfo(
{ metadata: metadata },
clientId,
secretKey,
);
return info;
}),
),
),
);
// create constructor param input for BaseRouter
@@ -179,29 +175,30 @@ export async function getDeploymentInfo(
finalDeploymentInfo.push(...extensionDeploymentInfo);
}
const implementationDeployInfo = await computeDeploymentInfo(
"implementation",
provider,
storage,
create2FactoryAddress,
{
metadata: compilerMetadata,
constructorParams: customParams,
},
clientId,
secretKey,
);
// get clone factory
const factoryInfo = await computeDeploymentInfo(
"infra",
provider,
storage,
create2FactoryAddress,
{ contractName: "TWCloneFactory" },
clientId,
secretKey,
);
const [implementationDeployInfo, factoryInfo] = await Promise.all([
computeDeploymentInfo(
"implementation",
provider,
storage,
create2FactoryAddress,
{
metadata: compilerMetadata,
constructorParams: customParams,
},
clientId,
secretKey,
),
// get clone factory
computeDeploymentInfo(
"infra",
provider,
storage,
create2FactoryAddress,
{ contractName: "TWCloneFactory" },
clientId,
secretKey,
),
]);
finalDeploymentInfo.push(factoryInfo);
finalDeploymentInfo.push(...Object.values(caches.deploymentPresets));
+7 -7
View File
@@ -46,8 +46,10 @@ export async function isTokenApprovedForTransfer(
): Promise<boolean> {
try {
const erc165 = new Contract(assetContract, ERC165Abi, provider) as IERC165;
const isERC721 = await erc165.supportsInterface(InterfaceId_IERC721);
const isERC1155 = await erc165.supportsInterface(InterfaceId_IERC1155);
const [isERC721, isERC1155] = await Promise.all([
erc165.supportsInterface(InterfaceId_IERC721),
erc165.supportsInterface(InterfaceId_IERC1155),
]);
if (isERC721) {
const asset = new Contract(assetContract, ERC721Abi, provider) as IERC721;
@@ -108,11 +110,9 @@ export async function handleTokenApproval(
contractWrapper.options,
contractWrapper.storage,
);
const isERC721 = await erc165.read("supportsInterface", [
InterfaceId_IERC721,
]);
const isERC1155 = await erc165.read("supportsInterface", [
InterfaceId_IERC1155,
const [isERC721, isERC1155] = await Promise.all([
erc165.read("supportsInterface", [InterfaceId_IERC721]),
erc165.read("supportsInterface", [InterfaceId_IERC1155]),
]);
// check for token approval
if (isERC721) {
@@ -73,6 +73,7 @@ import {
FEATURE_ACCOUNT,
FEATURE_ACCOUNT_FACTORY,
FEATURE_ACCOUNT_PERMISSIONS,
FEATURE_ACCOUNT_PERMISSIONS_V1,
} from "./thirdweb-features";
/**
@@ -146,6 +147,7 @@ export type Feature =
| typeof FEATURE_AIRDROP_ERC1155
| typeof FEATURE_ACCOUNT
| typeof FEATURE_ACCOUNT_PERMISSIONS
| typeof FEATURE_ACCOUNT_PERMISSIONS_V1
| typeof FEATURE_ACCOUNT_FACTORY;
export type Extension = Feature;
@@ -16,6 +16,7 @@ import IAirdropERC721 from "@thirdweb-dev/contracts-js/dist/abis/IAirdropERC721.
import IAirdropERC1155 from "@thirdweb-dev/contracts-js/dist/abis/IAirdropERC1155.json";
import IAccountFactoryCore from "@thirdweb-dev/contracts-js/dist/abis/IAccountFactoryCore.json";
import IAccountPermissions from "@thirdweb-dev/contracts-js/dist/abis/IAccountPermissions.json";
import IAccountPermissionsV1 from "@thirdweb-dev/contracts-js/dist/abis/IAccountPermissions_V1.json";
import IAccount from "@thirdweb-dev/contracts-js/dist/abis/IAccount.json";
export const getAllPluginsAbi = [
@@ -295,6 +296,18 @@ export const FEATURE_ACCOUNT_FACTORY = {
features: {},
} as const;
export const FEATURE_ACCOUNT_PERMISSIONS_V1 = {
name: "AccountPermissionsV1",
namespace: "accountPermissions",
docLinks: {
// TODO
sdk: "sdk.account",
contracts: "IAccountPermissions",
},
abis: [IAccountPermissionsV1],
features: {},
} as const;
export const FEATURE_ACCOUNT_PERMISSIONS = {
name: "AccountPermissions",
namespace: "accountPermissions",
@@ -316,7 +329,10 @@ export const FEATURE_ACCOUNT = {
contracts: "IAccount",
},
abis: [IAccount],
features: { [FEATURE_ACCOUNT_PERMISSIONS.name]: FEATURE_ACCOUNT_PERMISSIONS },
features: {
[FEATURE_ACCOUNT_PERMISSIONS.name]: FEATURE_ACCOUNT_PERMISSIONS,
[FEATURE_ACCOUNT_PERMISSIONS_V1.name]: FEATURE_ACCOUNT_PERMISSIONS_V1,
},
} as const;
export const FEATURE_AIRDROP_ERC20 = {
@@ -7,24 +7,30 @@ import { Transaction } from "./transactions";
import type {
IAccountCore,
IAccountPermissions,
IAccountPermissions_V1,
} from "@thirdweb-dev/contracts-js";
import invariant from "tiny-invariant";
import { resolveAddress } from "../../common";
import { detectContractFeature, resolveAddress } from "../../common";
import { resolveOrGenerateId } from "../../common/signature-minting";
import { buildTransactionFunction } from "../../common/transactions";
import { AddressOrEns } from "../../schema";
import {
AdminFlag,
DEFAULT_PERMISSIONS,
PermissionSnapshotInput,
PermissionSnapshotOutput,
PermissionSnapshotSchema,
SignedSignerPermissionsPayload,
SignedSignerPermissionsPayloadV1,
SignerPermissionRequest,
SignerPermissionRequestV1,
SignerPermissions,
SignerPermissionsInput,
SignerPermissionsOutput,
SignerPermissionsSchema,
SignerWithPermissions,
} from "../../types";
import { AddressZero } from "../../constants/addresses/AddressZero";
export class AccountPermissions implements DetectableFeature {
featureName = FEATURE_ACCOUNT_PERMISSIONS.name;
@@ -85,21 +91,44 @@ export class AccountPermissions implements DetectableFeature {
private async sendSignerPermissionRequest(
signerAddress: string,
permissions: SignerPermissionsOutput,
adminFlag: AdminFlag,
): Promise<Transaction> {
if (
detectContractFeature<IAccountPermissions_V1>(
this.contractWrapper,
"AccountPermissionsV1",
)
) {
// legacy account permissions contract
// admin is set only via EOA
// signer permissions are set via EOA or admin but no wildcard
if (
adminFlag === AdminFlag.AddAdmin ||
adminFlag === AdminFlag.RemoveAdmin
) {
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "setAdmin",
args: [signerAddress, adminFlag === AdminFlag.AddAdmin],
});
} else {
const { payload, signature } = await this.generateLegacyPayload(
signerAddress,
permissions,
);
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "setPermissionsForSigner",
args: [payload, signature],
});
}
}
const { payload, signature } = await this.generatePayload(
signerAddress,
permissions,
adminFlag,
);
const [success] = await this.contractWrapper.read(
"verifySignerPermissionRequest",
[payload, signature],
);
if (!success) {
throw new Error(`Invalid signature.`);
}
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "setPermissionsForSigner",
@@ -107,29 +136,6 @@ export class AccountPermissions implements DetectableFeature {
});
}
private async buildSignerPermissionRequest(
signerAddress: string,
permissions: SignerPermissionsOutput,
): Promise<string> {
const { payload, signature } = await this.generatePayload(
signerAddress,
permissions,
);
const isValidSigner = await this.contractWrapper.read(
"verifySignerPermissionRequest",
[payload, signature],
);
if (!isValidSigner) {
throw new Error(`Invalid signature.`);
}
return this.contractWrapper.writeContract.interface.encodeFunctionData(
"setPermissionsForSigner",
[payload, signature],
);
}
/**
* Generate and sign a payload to grant or revoke a signer's access to the account.
*
@@ -141,11 +147,16 @@ export class AccountPermissions implements DetectableFeature {
private async generatePayload(
signerAddress: string,
permissions: SignerPermissionsOutput,
isAdmin: AdminFlag,
): Promise<SignedSignerPermissionsPayload> {
// Get payload struct.
const payload: IAccountPermissions.SignerPermissionRequestStruct = {
signer: signerAddress,
approvedTargets: permissions.approvedCallTargets,
isAdmin: isAdmin.valueOf(),
approvedTargets:
permissions.approvedCallTargets === "*"
? [AddressZero]
: permissions.approvedCallTargets,
nativeTokenLimitPerTransaction: utils.parseEther(
permissions.nativeTokenLimitPerTransaction,
),
@@ -182,6 +193,53 @@ export class AccountPermissions implements DetectableFeature {
return { payload, signature };
}
private async generateLegacyPayload(
signerAddress: string,
permissions: SignerPermissionsOutput,
): Promise<SignedSignerPermissionsPayloadV1> {
if (permissions.approvedCallTargets === "*") {
throw new Error(
"Wildcard call targets are not supported on legacy account permissions contract, please deploy an updated contract factory.",
);
}
// legacy account permissions contract
// admin is set only via EOA
// signer permissions are set via EOA or admin but no wildcard
const payload: IAccountPermissions_V1.SignerPermissionRequestStruct = {
signer: signerAddress,
approvedTargets: permissions.approvedCallTargets,
nativeTokenLimitPerTransaction: utils.parseEther(
permissions.nativeTokenLimitPerTransaction,
),
permissionStartTimestamp: permissions.startDate,
permissionEndTimestamp: permissions.expirationDate,
reqValidityStartTimestamp: 0,
// Req validity ends 10 years from now.
reqValidityEndTimestamp: BigNumber.from(
Math.floor(
new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 10).getTime() /
1000,
),
),
uid: resolveOrGenerateId(undefined),
};
const chainId = await this.contractWrapper.getChainID();
const connectedSigner = this.contractWrapper.getSigner();
invariant(connectedSigner, "No signer available");
const signature = await this.contractWrapper.signTypedData(
connectedSigner,
{
name: "Account",
version: "1",
chainId,
verifyingContract: this.getAddress(),
},
{ SignerPermissionRequest: SignerPermissionRequestV1 },
payload,
);
return { payload, signature };
}
/*********************************
* READ FUNCTIONS
********************************/
@@ -320,11 +378,11 @@ export class AccountPermissions implements DetectableFeature {
grantAdminPermissions = /* @__PURE__ */ buildTransactionFunction(
async (signerAddress: AddressOrEns): Promise<Transaction> => {
const resolvedSignerAddress = await resolveAddress(signerAddress);
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "setAdmin",
args: [resolvedSignerAddress, true],
});
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
DEFAULT_PERMISSIONS,
AdminFlag.AddAdmin,
);
},
);
@@ -346,11 +404,11 @@ export class AccountPermissions implements DetectableFeature {
revokeAdminPermissions = /* @__PURE__ */ buildTransactionFunction(
async (signerAddress: AddressOrEns): Promise<Transaction> => {
const resolvedSignerAddress = await resolveAddress(signerAddress);
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "setAdmin",
args: [resolvedSignerAddress, false],
});
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
DEFAULT_PERMISSIONS,
AdminFlag.RemoveAdmin,
);
},
);
@@ -395,6 +453,7 @@ export class AccountPermissions implements DetectableFeature {
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
resolvedPermissions,
AdminFlag.None,
);
},
);
@@ -440,6 +499,7 @@ export class AccountPermissions implements DetectableFeature {
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
resolvedPermissions,
AdminFlag.None,
);
},
);
@@ -475,12 +535,16 @@ export class AccountPermissions implements DetectableFeature {
);
}
return await this.sendSignerPermissionRequest(resolvedSignerAddress, {
startDate: BigNumber.from(0),
expirationDate: BigNumber.from(0),
approvedCallTargets: [],
nativeTokenLimitPerTransaction: "0",
});
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
{
startDate: BigNumber.from(0),
expirationDate: BigNumber.from(0),
approvedCallTargets: [],
nativeTokenLimitPerTransaction: "0",
},
AdminFlag.None,
);
},
);
@@ -531,13 +595,17 @@ export class AccountPermissions implements DetectableFeature {
const newTargets = [...permissions.approvedTargets, resolvedTarget];
return await this.sendSignerPermissionRequest(resolvedSignerAddress, {
startDate: BigNumber.from(permissions.startTimestamp),
expirationDate: BigNumber.from(permissions.endTimestamp),
approvedCallTargets: newTargets,
nativeTokenLimitPerTransaction:
permissions.nativeTokenLimitPerTransaction.toString(),
});
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
{
startDate: BigNumber.from(permissions.startTimestamp),
expirationDate: BigNumber.from(permissions.endTimestamp),
approvedCallTargets: newTargets,
nativeTokenLimitPerTransaction:
permissions.nativeTokenLimitPerTransaction.toString(),
},
AdminFlag.None,
);
},
);
@@ -591,13 +659,17 @@ export class AccountPermissions implements DetectableFeature {
utils.getAddress(approvedTarget) !== utils.getAddress(resolvedTarget),
);
return await this.sendSignerPermissionRequest(resolvedSignerAddress, {
startDate: BigNumber.from(permissions.startTimestamp),
expirationDate: BigNumber.from(permissions.endTimestamp),
approvedCallTargets: newTargets,
nativeTokenLimitPerTransaction:
permissions.nativeTokenLimitPerTransaction.toString(),
});
return await this.sendSignerPermissionRequest(
resolvedSignerAddress,
{
startDate: BigNumber.from(permissions.startTimestamp),
expirationDate: BigNumber.from(permissions.endTimestamp),
approvedCallTargets: newTargets,
nativeTokenLimitPerTransaction:
permissions.nativeTokenLimitPerTransaction.toString(),
},
AdminFlag.None,
);
},
);
@@ -651,14 +723,16 @@ export class AccountPermissions implements DetectableFeature {
const allToMakeAdmin = resolvedSnapshot
.filter((item) => item.makeAdmin)
.map((item) => item.signer);
allAdmins.forEach((admin) => {
allAdmins.forEach(async (admin) => {
if (!allToMakeAdmin.includes(admin)) {
removeAdminData.push(
this.contractWrapper.writeContract.interface.encodeFunctionData(
"setAdmin",
[admin, false],
),
);
const data = (
await this.sendSignerPermissionRequest(
admin,
DEFAULT_PERMISSIONS,
AdminFlag.RemoveAdmin,
)
).encode();
removeAdminData.push(data);
}
});
@@ -672,13 +746,13 @@ export class AccountPermissions implements DetectableFeature {
await Promise.all(
allSigners.map(async (item) => {
if (!allToMakeSigners.includes(item.signer)) {
const data = await this.buildSignerPermissionRequest(item.signer, {
startDate: BigNumber.from(0),
expirationDate: BigNumber.from(0),
approvedCallTargets: [],
nativeTokenLimitPerTransaction: "0",
});
const data = (
await this.sendSignerPermissionRequest(
item.signer,
DEFAULT_PERMISSIONS,
AdminFlag.None,
)
).encode();
removeSignerData.push(data);
}
}),
@@ -687,18 +761,23 @@ export class AccountPermissions implements DetectableFeature {
for (const member of resolvedSnapshot) {
// Add new admin
if (member.makeAdmin) {
addAdminData.push(
this.contractWrapper.writeContract.interface.encodeFunctionData(
"setAdmin",
[member.signer, true],
),
);
const data = (
await this.sendSignerPermissionRequest(
member.signer,
DEFAULT_PERMISSIONS,
AdminFlag.AddAdmin,
)
).encode();
addAdminData.push(data);
} else {
// Add new scoped
const data = await this.buildSignerPermissionRequest(
member.signer,
member.permissions,
);
const data = (
await this.sendSignerPermissionRequest(
member.signer,
member.permissions,
AdminFlag.None,
)
).encode();
addOrUpdateSignerData.push(data);
}
}
+5 -1
View File
@@ -13,8 +13,8 @@ import {
SignerPermissionsInput,
SignerWithPermissions,
} from "../../types";
import { AccountPermissions } from "./account-permissions";
import { buildTransactionFunction } from "../../common/transactions";
import { AccountPermissions } from "./account-permissions";
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- TO BE REMOVED IN V4
export class Account<TContract extends IAccountCore>
@@ -34,6 +34,10 @@ export class Account<TContract extends IAccountCore>
detectContractFeature<IAccountCore>(
this.contractWrapper,
"AccountPermissions",
) ||
detectContractFeature<IAccountCore>(
this.contractWrapper,
"AccountPermissionsV1",
)
) {
return new AccountPermissions(this.contractWrapper);
@@ -7,9 +7,11 @@ import {
AbiEvent,
AbiFunction,
AbiSchema,
ContractSource,
PublishedMetadata,
} from "../../schema/contracts/custom";
import { ContractWrapper } from "./contract-wrapper";
import { fetchSourceFilesFromMetadata } from "../../common";
/**
* Handles publish metadata for a contract
@@ -47,6 +49,14 @@ export class ContractPublishedMetadata<TContract extends BaseContract> {
return this._cachedMetadata;
}
/**
* @public
*/
public async extractSources(): Promise<ContractSource[]> {
const publishedMetadata = await this.get();
return fetchSourceFilesFromMetadata(publishedMetadata, this.storage);
}
/**
* @public
*/
@@ -27,6 +27,7 @@ import { buildTransactionFunction } from "../../common/transactions";
import { isIncrementalVersion } from "../../common/version-checker";
import { getContractPublisherAddress } from "../../constants/addresses/getContractPublisherAddress";
import {
Abi,
AbiFunction,
AbiSchema,
ContractParam,
@@ -41,6 +42,7 @@ import {
PublishedContract,
PublishedContractFetched,
PublishedContractSchema,
PublishedMetadata,
} from "../../schema/contracts/custom";
import { SDKOptions } from "../../schema/sdk-options";
import { AddressOrEns } from "../../schema/shared/AddressOrEnsSchema";
@@ -137,10 +139,11 @@ export class ContractPublisher extends RPCConnectionHandler {
}
/**
* @internal
* @param address
*/
public async fetchCompilerMetadataFromAddress(address: AddressOrEns) {
public async fetchCompilerMetadataFromAddress(
address: AddressOrEns,
): Promise<PublishedMetadata> {
const resolvedAddress = await resolveAddress(address);
return fetchContractMetadataFromAddress(
resolvedAddress,
@@ -217,7 +220,7 @@ export class ContractPublisher extends RPCConnectionHandler {
}
/**
* @internal
* Fetch all sources for a contract from its address
* @param address
*/
public async fetchContractSourcesFromAddress(
@@ -230,6 +233,22 @@ export class ContractPublisher extends RPCConnectionHandler {
return await fetchSourceFilesFromMetadata(metadata, this.storage);
}
/**
* Fetch ABI from a contract, or undefined if not found
* @param address
*/
public async fetchContractAbiFromAddress(
address: AddressOrEns,
): Promise<Abi | undefined> {
const resolvedAddress = await resolveAddress(address);
const meta = await fetchContractMetadataFromAddress(
resolvedAddress,
this.getProvider(),
this.storage,
);
return meta.abi;
}
/**
* @internal
* @param profileMetadata
@@ -100,11 +100,14 @@ export class DropClaimConditions<
public async getActive(
options?: ClaimConditionFetchOptions,
): Promise<ClaimCondition> {
const cc = await this.get();
const metadata = await this.metadata.get();
const [cc, metadata, tokenDecimals] = await Promise.all([
this.get(),
this.metadata.get(),
this.getTokenDecimals(),
]);
return await transformResultToClaimCondition(
cc,
await this.getTokenDecimals(),
tokenDecimals,
this.contractWrapper.getProvider(),
metadata.merkle || {},
this.storage,
@@ -236,12 +239,6 @@ export class DropClaimConditions<
let activeConditionIndex: BigNumber;
let claimCondition: ClaimCondition;
const decimals = await this.getTokenDecimals();
const quantityWithDecimals = utils.parseUnits(
AmountSchema.parse(quantity),
decimals,
);
if (addressToCheck === undefined) {
try {
addressToCheck = await this.contractWrapper.getSignerAddress();
@@ -255,7 +252,15 @@ export class DropClaimConditions<
return [ClaimEligibility.NoWallet];
}
const resolvedAddress = await resolveAddress(addressToCheck);
const [resolvedAddress, decimals] = await Promise.all([
resolveAddress(addressToCheck),
this.getTokenDecimals(),
]);
const quantityWithDecimals = utils.parseUnits(
AmountSchema.parse(quantity),
decimals,
);
try {
claimCondition = await this.getActive();
@@ -487,7 +492,7 @@ export class DropClaimConditions<
}
}
// if not within a browser conetext, check for wallet balance.
// if not within a browser context, check for wallet balance.
// In browser context, let the wallet do that job
if (claimCondition.price.gt(0) && isNode()) {
const totalPrice = claimCondition.price.mul(BigNumber.from(quantity));
@@ -528,8 +533,10 @@ export class DropClaimConditions<
const merkleRoot = claimCondition.merkleRoot;
const merkleRootArray = utils.stripZeros(merkleRoot);
if (merkleRootArray.length > 0) {
const metadata = await this.metadata.get();
const resolvedAddress = await resolveAddress(claimerAddress);
const [metadata, resolvedAddress] = await Promise.all([
this.metadata.get(),
resolveAddress(claimerAddress),
]);
return await fetchSnapshotEntryForAddress(
resolvedAddress,
merkleRoot.toString(),
@@ -820,13 +827,14 @@ export class DropClaimConditions<
decimals = 0,
address?: string,
): Promise<ClaimVerification> {
const addressToClaim = address
? address
: await this.contractWrapper.getSignerAddress();
const [addressToClaim, activeClaimConditions] = await Promise.all([
address ? address : this.contractWrapper.getSignerAddress(),
this.getActive(),
]);
return prepareClaim(
addressToClaim,
quantity,
await this.getActive(),
activeClaimConditions,
async () => (await this.metadata.get()).merkle,
decimals,
this.contractWrapper,
@@ -15,7 +15,6 @@ import { generateExtensionFunctions } from "../../common/plugin/generatePluginFu
import { Abi, AbiSchema, CommonContractSchema } from "../../schema";
import { utils } from "ethers";
import invariant from "tiny-invariant";
import { ExtensionAddedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/CoreRouter";
import {
THIRDWEB_DEPLOYER,
deployContractDeterministic,
@@ -26,9 +25,12 @@ import {
} from "../../common";
import { joinABIs } from "../../common/plugin/joinABIs";
import { TransactionReceipt } from "@ethersproject/abstract-provider";
import { ExtensionRemovedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/CoreRouter";
import { ExtensionReplacedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/BaseRouter";
import { DynamicContractExtensionMetadataOrUri } from "../../types";
import {
ExtensionAddedEvent,
ExtensionRemovedEvent,
ExtensionReplacedEvent,
} from "@thirdweb-dev/contracts-js/dist/declarations/src/BaseRouter";
export class ExtensionManager implements DetectableFeature {
featureName = FEATURE_DYNAMIC_CONTRACT.name;
@@ -285,12 +285,11 @@ export class MarketplaceAuction {
async (
listings: NewAuctionListing[],
): Promise<Transaction<TransactionResultWithId[]>> => {
const data = await Promise.all(
listings.map(async (listing) => {
const tx = await this.createListing.prepare(listing);
return tx.encode();
}),
);
const data = (
await Promise.all(
listings.map((listing) => this.createListing.prepare(listing)),
)
).map((tx) => tx.encode());
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
@@ -576,7 +575,7 @@ export class MarketplaceAuction {
const [currentBidBufferBps, winningBid, listing] = await Promise.all([
this.getBidBufferBps(),
this.getWinningBid(listingId),
await this.validateListing(BigNumber.from(listingId)),
this.validateListing(BigNumber.from(listingId)),
]);
const currentBidOrReservePrice = winningBid
@@ -239,12 +239,11 @@ export class MarketplaceDirect {
async (
listings: NewDirectListing[],
): Promise<Transaction<TransactionResultWithId[]>> => {
const data = await Promise.all(
listings.map(async (listing) => {
const tx = await this.createListing.prepare(listing);
return tx.encode();
}),
);
const data = (
await Promise.all(
listings.map((listing) => this.createListing.prepare(listing)),
)
).map((tx) => tx.encode());
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
@@ -414,12 +414,11 @@ export class MarketplaceV3DirectListings<TContract extends DirectListingsLogic>
async (
listings: DirectListingInputParams[],
): Promise<Transaction<TransactionResultWithId[]>> => {
const data = await Promise.all(
listings.map(async (listing) => {
const tx = await this.createListing.prepare(listing);
return tx.encode();
}),
);
const data = (
await Promise.all(
listings.map((listing) => this.createListing.prepare(listing)),
)
).map((tx) => tx.encode());
return Transaction.fromContractWrapper({
contractWrapper: this
@@ -404,12 +404,11 @@ export class MarketplaceV3EnglishAuctions<
async (
listings: EnglishAuctionInputParams[],
): Promise<Transaction<TransactionResultWithId[]>> => {
const data = await Promise.all(
listings.map(async (listing) => {
const tx = await this.createAuction.prepare(listing);
return tx.encode();
}),
);
const data = (
await Promise.all(
listings.map((listing) => this.createAuction.prepare(listing)),
)
).map((tx) => tx.encode());
return Transaction.fromContractWrapper({
contractWrapper: this
+38 -3
View File
@@ -1,4 +1,7 @@
import type { IAccountPermissions } from "@thirdweb-dev/contracts-js";
import type {
IAccountPermissions,
IAccountPermissions_V1,
} from "@thirdweb-dev/contracts-js";
import { BigNumber, BytesLike } from "ethers";
import { z } from "zod";
import { AmountSchema } from "../../core/schema/shared";
@@ -12,12 +15,27 @@ export type SignerPermissions = {
approvedCallTargets: string[];
};
export enum AdminFlag {
None = 0,
AddAdmin = 1,
RemoveAdmin = 2,
}
export const DEFAULT_PERMISSIONS = {
// eslint-disable-next-line better-tree-shaking/no-top-level-side-effects
startDate: BigNumber.from(0),
// eslint-disable-next-line better-tree-shaking/no-top-level-side-effects
expirationDate: BigNumber.from(0),
approvedCallTargets: [],
nativeTokenLimitPerTransaction: "0",
};
export const SignerPermissionsSchema = /* @__PURE__ */ (() =>
z.object({
startDate: StartDateSchema,
expirationDate: EndDateSchema,
nativeTokenLimitPerTransaction: AmountSchema.default(0),
approvedCallTargets: z.array(AddressOrEnsSchema),
approvedCallTargets: z.union([z.array(AddressOrEnsSchema), z.literal("*")]),
}))();
export type SignerPermissionsInput = z.input<typeof SignerPermissionsSchema>;
@@ -48,7 +66,12 @@ export type SignedSignerPermissionsPayload = {
signature: BytesLike;
};
export const SignerPermissionRequest = [
export type SignedSignerPermissionsPayloadV1 = {
payload: IAccountPermissions_V1.SignerPermissionRequestStruct;
signature: BytesLike;
};
export const SignerPermissionRequestV1 = [
{ name: "signer", type: "address" },
{ name: "approvedTargets", type: "address[]" },
{ name: "nativeTokenLimitPerTransaction", type: "uint256" },
@@ -58,3 +81,15 @@ export const SignerPermissionRequest = [
{ name: "reqValidityEndTimestamp", type: "uint128" },
{ name: "uid", type: "bytes32" },
];
export const SignerPermissionRequest = [
{ name: "signer", type: "address" },
{ name: "isAdmin", type: "uint8" },
{ name: "approvedTargets", type: "address[]" },
{ name: "nativeTokenLimitPerTransaction", type: "uint256" },
{ name: "permissionStartTimestamp", type: "uint128" },
{ name: "permissionEndTimestamp", type: "uint128" },
{ name: "reqValidityStartTimestamp", type: "uint128" },
{ name: "reqValidityEndTimestamp", type: "uint128" },
{ name: "uid", type: "bytes32" },
];
+112 -57
View File
@@ -9,7 +9,6 @@ import {
} from "../../src/evm";
import { ContractFactory, utils } from "ethers";
import EntrypointArtifact from "./mock/EntryPoint.json";
import AccountFactoryArtifact from "./mock/AccountFactory.json";
// Target ABIs
import IAccountCoreAbi from "@thirdweb-dev/contracts-js/dist/abis/IAccountCore.json";
@@ -17,7 +16,12 @@ import {
deployContractAndUploadMetadata,
mockUploadContractMetadata,
} from "./utils";
import { IAccountCore, IAccountFactory } from "@thirdweb-dev/contracts-js";
import {
AccountFactory__factory,
IAccountCore,
IAccountFactory,
} from "@thirdweb-dev/contracts-js";
import { AddressZero } from "../../src/evm/constants/addresses/AddressZero";
describe("Accounts with account factory", function () {
let accountFactory: AccountFactory<IAccountFactory>;
@@ -57,8 +61,8 @@ describe("Accounts with account factory", function () {
adminWallet,
).deploy();
const factoryAddress = await deployContractAndUploadMetadata(
AccountFactoryArtifact.abi,
AccountFactoryArtifact.bytecode.object,
AccountFactory__factory.abi,
AccountFactory__factory.bytecode,
adminWallet,
[entrypoint.address],
);
@@ -124,8 +128,8 @@ describe("Accounts with account factory", function () {
accountAddress,
IAccountCoreAbi,
);
const account = (await sdk.getContract(accountAddress)).account;
const allAdmins = await account.getAllAdmins();
const acc = (await sdk.getContract(accountAddress)).account;
const allAdmins = await acc.getAllAdmins();
assert.isTrue(
allAdmins.length === 1,
"Account should only have one admin.",
@@ -139,8 +143,9 @@ describe("Accounts with account factory", function () {
"Correct admin for account.",
);
const associatedAccounts =
await accountFactory.getAssociatedAccounts(admin);
const associatedAccounts = await accountFactory.getAssociatedAccounts(
admin,
);
assert.isTrue(
associatedAccounts.length === 1,
@@ -185,65 +190,65 @@ describe("Accounts with account factory", function () {
account = (await sdk.getContract(accountAddress)).account;
});
// it("Should be able to add another admin to the account.", async () => {
// assert.isFalse(
// await account.isAdmin(signer1Wallet.address),
// "New signer1 should not be an admin on the account.",
// );
it("Should be able to add another admin to the account.", async () => {
assert.isFalse(
await account.isAdmin(signer1Wallet.address),
"New signer1 should not be an admin on the account.",
);
// await account.grantAdminPermissions(signer1Wallet.address);
await account.grantAdminPermissions(signer1Wallet.address);
// assert.isTrue(
// await account.isAdmin(signer1Wallet.address),
// "New signer1 should be an admin on the account.",
// );
assert.isTrue(
await account.isAdmin(signer1Wallet.address),
"New signer1 should be an admin on the account.",
);
// const isAdmin = (await account.getAllAdmins()).includes(
// utils.getAddress(signer1Wallet.address),
// );
const isAdmin = (await account.getAllAdmins()).includes(
utils.getAddress(signer1Wallet.address),
);
// assert.isTrue(isAdmin, "New signer1 should be an admin on the account.");
assert.isTrue(isAdmin, "New signer1 should be an admin on the account.");
// assert.isTrue(
// (
// await accountFactory.getAssociatedAccounts(signer1Wallet.address)
// ).includes(account.getAddress()),
// "Wallet is an associated account of the signer.",
// );
// });
assert.isTrue(
(
await accountFactory.getAssociatedAccounts(signer1Wallet.address)
).includes(account.getAddress()),
"Wallet is an associated account of the signer.",
);
});
// it("Should be able to remove an admin from the account.", async () => {
// await account.grantAdminPermissions(signer1Wallet.address);
// assert.isTrue(
// await account.isAdmin(signer1Wallet.address),
// "New signer1 should be an admin on the account.",
// );
it("Should be able to remove an admin from the account.", async () => {
await account.grantAdminPermissions(signer1Wallet.address);
assert.isTrue(
await account.isAdmin(signer1Wallet.address),
"New signer1 should be an admin on the account.",
);
// await account.revokeAdminPermissions(signer1Wallet.address);
await account.revokeAdminPermissions(signer1Wallet.address);
// assert.isFalse(
// await account.isAdmin(signer1Wallet.address),
// "New signer1 should not be an admin on the account.",
// );
assert.isFalse(
await account.isAdmin(signer1Wallet.address),
"New signer1 should not be an admin on the account.",
);
// assert.isFalse(
// (await account.getAllSigners())
// .map((result) => utils.getAddress(result.signer))
// .includes(signer1Wallet.address),
// "New signer1 should not be an admin on the account.",
// );
assert.isFalse(
(await account.getAllSigners())
.map((result) => utils.getAddress(result.signer))
.includes(signer1Wallet.address),
"New signer1 should not be an admin on the account.",
);
// assert.isFalse(
// (await account.getAllAdmins()).includes(signer1Wallet.address),
// "New signer1 is not an associated signer of the account.",
// );
// assert.isFalse(
// (
// await accountFactory.getAssociatedAccounts(signer1Wallet.address)
// ).includes(account.getAddress()),
// "Wallet is not an associated account of the signer.",
// );
// });
assert.isFalse(
(await account.getAllAdmins()).includes(signer1Wallet.address),
"New signer1 is not an associated signer of the account.",
);
assert.isFalse(
(
await accountFactory.getAssociatedAccounts(signer1Wallet.address)
).includes(account.getAddress()),
"Wallet is not an associated account of the signer.",
);
});
it("Should be able to grant restricted access to a new signer.", async () => {
const signersWithRestrictions = await account.getAllSigners();
@@ -306,6 +311,56 @@ describe("Accounts with account factory", function () {
);
});
it("Should be able to restrict approved targets.", async () => {
// Grant access
await account.grantPermissions(signer1Wallet.address, {
nativeTokenLimitPerTransaction: "1",
approvedCallTargets: [adminWallet.address],
});
const s = await account.getAllSigners();
const restrictions = s.find(
(result) =>
utils.getAddress(result.signer) ===
utils.getAddress(signer1Wallet.address),
)?.permissions as SignerPermissions;
assert.strictEqual(
restrictions.approvedCallTargets.length,
1,
"New signer1 should have one approved call targets.",
);
assert.strictEqual(
restrictions.approvedCallTargets[0],
adminWallet.address,
"New signer1 should have the expected approved call targets.",
);
});
it("Should be able to approve any target.", async () => {
// Grant access
await account.grantPermissions(signer1Wallet.address, {
nativeTokenLimitPerTransaction: "1",
approvedCallTargets: "*",
});
const s = await account.getAllSigners();
const restrictions = s.find(
(result) =>
utils.getAddress(result.signer) ===
utils.getAddress(signer1Wallet.address),
)?.permissions as SignerPermissions;
assert.strictEqual(
restrictions.approvedCallTargets.length,
1,
"New signer1 should have one approved call targets.",
);
assert.strictEqual(
restrictions.approvedCallTargets[0],
AddressZero,
"New signer1 should have the expected approved call targets.",
);
});
it("Should not be able to grant restricted access to a signer who already has access.", async () => {
// Grant access to signer1
await account.grantPermissions(signer1Wallet.address, {
+2 -2
View File
@@ -230,7 +230,7 @@ export const mochaHooks = {
if (contractType === "custom" || contractType === "marketplace-v3") {
continue;
}
let factories: any[] = [];
const factories: any[] = [];
switch (contractType) {
case TokenInitializer.contractType:
factories.push(TokenERC20__factory);
@@ -367,7 +367,7 @@ async function setupMultichainRegistry(
// Setup marketplace-v3 for tests
async function setupMarketplaceV3(): Promise<string> {
let extensions: Extension[] = [];
const extensions: Extension[] = [];
// Direct Listings
const directListingsExtensionAddress = await deployContractAndUploadMetadata(
+46
View File
@@ -1,5 +1,51 @@
# @thirdweb-dev/unity-js-bridge
## 0.2.93
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
- @thirdweb-dev/sdk@4.0.6
- @thirdweb-dev/wallets@2.0.7
- @thirdweb-dev/auth@4.0.7
## 0.2.92
### Patch Changes
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
- @thirdweb-dev/sdk@4.0.5
- @thirdweb-dev/wallets@2.0.6
- @thirdweb-dev/auth@4.0.6
## 0.2.91
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@4.0.4
- @thirdweb-dev/wallets@2.0.5
- @thirdweb-dev/auth@4.0.5
## 0.2.90
### Patch Changes
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/sdk@4.0.3
- @thirdweb-dev/wallets@2.0.4
- @thirdweb-dev/auth@4.0.4
## 0.2.89
### Patch Changes
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
- @thirdweb-dev/sdk@4.0.2
- @thirdweb-dev/wallets@2.0.3
- @thirdweb-dev/auth@4.0.3
## 0.2.88
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/unity-js-bridge",
"version": "0.2.88",
"version": "0.2.93",
"main": "dist/thirdweb-unity-bridge.js",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
"license": "Apache-2.0",
+38
View File
@@ -1,5 +1,43 @@
# @thirdweb-dev/wallets
## 2.0.7
### Patch Changes
- Updated dependencies [[`137f46a5`](https://github.com/thirdweb-dev/js/commit/137f46a5470d2b5f9d7f9eda9b2d839a53ddeb64)]:
- @thirdweb-dev/chains@0.1.55
- @thirdweb-dev/sdk@4.0.6
## 2.0.6
### Patch Changes
- Updated dependencies [[`07544252`](https://github.com/thirdweb-dev/js/commit/07544252b49163e1ae84ba2cc76b99597a1c4553)]:
- @thirdweb-dev/sdk@4.0.5
## 2.0.5
### Patch Changes
- Updated dependencies [[`6c30b7ef`](https://github.com/thirdweb-dev/js/commit/6c30b7efc708e1244f3be3e10eac8f3b8b14a8c3)]:
- @thirdweb-dev/contracts-js@1.3.16
- @thirdweb-dev/sdk@4.0.4
## 2.0.4
### Patch Changes
- Updated dependencies [[`956b5645`](https://github.com/thirdweb-dev/js/commit/956b5645e4266cba536abd27ee250dab5aa9a177)]:
- @thirdweb-dev/contracts-js@1.3.15
- @thirdweb-dev/sdk@4.0.3
## 2.0.3
### Patch Changes
- Updated dependencies [[`526176c4`](https://github.com/thirdweb-dev/js/commit/526176c47108c91d83bcfc5f0ca556274e6462d6), [`d1f8e951`](https://github.com/thirdweb-dev/js/commit/d1f8e951623f1691fdfe3d1e8645970d0a52eb06), [`09120c92`](https://github.com/thirdweb-dev/js/commit/09120c923cca804b9d4f5f779e5a53c97ecc8223), [`6573556d`](https://github.com/thirdweb-dev/js/commit/6573556d0e03efa0d6a157fccb0a1c08dd22d7cd)]:
- @thirdweb-dev/sdk@4.0.2
## 2.0.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/wallets",
"version": "2.0.2",
"version": "2.0.7",
"main": "dist/thirdweb-dev-wallets.cjs.js",
"module": "dist/thirdweb-dev-wallets.esm.js",
"types": "dist/thirdweb-dev-wallets.cjs.d.ts",
+29 -6
View File
@@ -380,8 +380,8 @@ importers:
packages/contracts-js:
dependencies:
'@thirdweb-dev/contracts':
specifier: 3.10.2-3
version: 3.10.2-3([email protected])
specifier: 3.10.3
version: 3.10.3([email protected])
devDependencies:
'@babel/preset-env':
specifier: ^7.22.9
@@ -827,6 +827,9 @@ importers:
react-native-device-info:
specifier: 10.6.0
version: 10.6.0([email protected])
react-native-inappbrowser-reborn:
specifier: ^3.7.0
version: 3.7.0([email protected])
react-native-quick-base64:
specifier: ^2.0.7
version: 2.0.7([email protected])([email protected])
@@ -12030,8 +12033,9 @@ packages:
use-sync-external-store: 1.2.0([email protected])
dev: false
/@thirdweb-dev/[email protected].2-3([email protected]):
resolution: {integrity: sha512-QWO9HT4k3s86oMyE/SbDWhgm/Na9FnxOkVjhyuOigmrwq5NlNp7NCcmecQgILxvUiLXO9if9OeFlYCFGsJinng==}
/@thirdweb-dev/[email protected]([email protected]):
resolution: {integrity: sha512-wSVNaEoosn0AgUtnxlvv7rgK+3EUMzJm2ZasofPgJgqGS3gYH5nDBmK29VMquA2BLc38OAPyYMWc/iQCiCikMg==}
engines: {node: '>=18.0.0'}
dependencies:
'@chainlink/contracts': 0.6.1([email protected])
'@openzeppelin/contracts': 4.9.3
@@ -17542,7 +17546,7 @@ packages:
minimatch: 3.1.2
object.values: 1.1.6
resolve: 1.22.1
semver: 7.5.4
semver: 7.5.3
tsconfig-paths: 3.14.2
transitivePeerDependencies:
- eslint-import-resolver-typescript
@@ -23999,6 +24003,13 @@ packages:
is-docker: 2.2.1
is-wsl: 2.2.0
/[email protected]:
resolution: {integrity: sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==}
hasBin: true
requiresBuild: true
dev: false
optional: true
/[email protected]:
resolution: {integrity: sha512-hgJa2aQKcM2hn3eyVtN12tEA45ECjTJPXCgUh5YzTzy9qwapCvmDTVPWOcWVL0d34zeQoQ/hbG9lJhl3AYxJlQ==}
dependencies:
@@ -25539,7 +25550,7 @@ packages:
engines: {node: '>=12.0.0'}
hasBin: true
peerDependencies:
protobufjs: ^7.0.0
protobufjs: '>=7.2.4'
dependencies:
chalk: 4.1.2
escodegen: 1.14.3
@@ -25910,6 +25921,18 @@ packages:
/[email protected]:
resolution: {integrity: sha512-1dVk9NwhoyKHCSxcrM6vY6cxmojeATsBobDicX0ZKr7DgUF2cBQRTKsimQFvzH8XhOVXyH8p4HyDSZNIFI8OlQ==}
/[email protected]([email protected]):
resolution: {integrity: sha512-Ia53jYNtFcbNaX5W3QfOmN25I7bcvuDiQmSY5zABXjy4+WI20bPc9ua09li55F8yDCjv3C99jX6vKms68mBV7g==}
requiresBuild: true
peerDependencies:
react-native: '>=0.56'
dependencies:
invariant: 2.2.4
opencollective-postinstall: 2.0.3
react-native: 0.71.11(@babel/[email protected])(@babel/[email protected])([email protected])
dev: false
optional: true
/[email protected]([email protected])([email protected]):
resolution: {integrity: sha512-0hYNOTbsjJ5j5cpX+qjwReGIxuYE9MWRsyPQ72fTOvzmEjYXCF4Wr2VQoqx8R6W1/Uinekvln7dGvJ4RExmHhQ==}
peerDependencies: