thirdweb 5.46.2-nightly-997c3945a7673517fb28273a9985f70ff892b365-20240817000330 → 5.47.0-nightly-f0d6e343eea28cd49863ba4794b89d6b070c52b2-20240818000714
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/auth/verify-hash.js +24 -0
- package/dist/cjs/auth/verify-hash.js.map +1 -1
- package/dist/cjs/exports/extensions/erc20.js +5 -1
- package/dist/cjs/exports/extensions/erc20.js.map +1 -1
- package/dist/cjs/exports/extensions/thirdweb.js +45 -0
- package/dist/cjs/exports/extensions/thirdweb.js.map +1 -0
- package/dist/cjs/exports/extensions/vote.js +14 -1
- package/dist/cjs/exports/extensions/vote.js.map +1 -1
- package/dist/cjs/exports/react.js +6 -1
- package/dist/cjs/exports/react.js.map +1 -1
- package/dist/cjs/extensions/prebuilts/deploy-split.js +1 -0
- package/dist/cjs/extensions/prebuilts/deploy-split.js.map +1 -1
- package/dist/cjs/extensions/vote/read/canExecute.js +28 -0
- package/dist/cjs/extensions/vote/read/canExecute.js.map +1 -0
- package/dist/cjs/extensions/vote/read/getAll.js +52 -0
- package/dist/cjs/extensions/vote/read/getAll.js.map +1 -0
- package/dist/cjs/extensions/vote/read/getProposalVoteCounts.js +32 -0
- package/dist/cjs/extensions/vote/read/getProposalVoteCounts.js.map +1 -0
- package/dist/cjs/extensions/vote/read/proposalExists.js +28 -0
- package/dist/cjs/extensions/vote/read/proposalExists.js.map +1 -0
- package/dist/cjs/extensions/vote/types.js +21 -0
- package/dist/cjs/extensions/vote/types.js.map +1 -0
- package/dist/cjs/extensions/vote/write/executeProposal.js +56 -0
- package/dist/cjs/extensions/vote/write/executeProposal.js.map +1 -0
- package/dist/cjs/react/core/utils/wallet.js +2 -2
- package/dist/cjs/react/core/utils/wallet.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/Blobbie.js +54 -0
- package/dist/cjs/react/web/ui/ConnectWallet/Blobbie.js.map +1 -0
- package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js +8 -8
- package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/Details.js +23 -22
- package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
- package/dist/cjs/react/web/ui/ConnectWallet/locale/en.js +2 -2
- package/dist/cjs/react/web/ui/ConnectWallet/locale/en.js.map +1 -1
- package/dist/cjs/react/web/ui/TransactionButton/index.js +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/auth/verify-hash.js +24 -0
- package/dist/esm/auth/verify-hash.js.map +1 -1
- package/dist/esm/exports/extensions/erc20.js +2 -0
- package/dist/esm/exports/extensions/erc20.js.map +1 -1
- package/dist/esm/exports/extensions/thirdweb.js +28 -0
- package/dist/esm/exports/extensions/thirdweb.js.map +1 -0
- package/dist/esm/exports/extensions/vote.js +6 -0
- package/dist/esm/exports/extensions/vote.js.map +1 -1
- package/dist/esm/exports/react.js +4 -0
- package/dist/esm/exports/react.js.map +1 -1
- package/dist/esm/extensions/prebuilts/deploy-split.js +1 -0
- package/dist/esm/extensions/prebuilts/deploy-split.js.map +1 -1
- package/dist/esm/extensions/vote/read/canExecute.js +25 -0
- package/dist/esm/extensions/vote/read/canExecute.js.map +1 -0
- package/dist/esm/extensions/vote/read/getAll.js +49 -0
- package/dist/esm/extensions/vote/read/getAll.js.map +1 -0
- package/dist/esm/extensions/vote/read/getProposalVoteCounts.js +29 -0
- package/dist/esm/extensions/vote/read/getProposalVoteCounts.js.map +1 -0
- package/dist/esm/extensions/vote/read/proposalExists.js +25 -0
- package/dist/esm/extensions/vote/read/proposalExists.js.map +1 -0
- package/dist/esm/extensions/vote/types.js +18 -0
- package/dist/esm/extensions/vote/types.js.map +1 -0
- package/dist/esm/extensions/vote/write/executeProposal.js +52 -0
- package/dist/esm/extensions/vote/write/executeProposal.js.map +1 -0
- package/dist/esm/react/core/utils/wallet.js +2 -2
- package/dist/esm/react/core/utils/wallet.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/Blobbie.js +51 -0
- package/dist/esm/react/web/ui/ConnectWallet/Blobbie.js.map +1 -0
- package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js +8 -8
- package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/Details.js +24 -23
- package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
- package/dist/esm/react/web/ui/ConnectWallet/locale/en.js +2 -2
- package/dist/esm/react/web/ui/ConnectWallet/locale/en.js.map +1 -1
- package/dist/esm/react/web/ui/TransactionButton/index.js +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/types/auth/verify-hash.d.ts.map +1 -1
- package/dist/types/exports/extensions/erc20.d.ts +2 -0
- package/dist/types/exports/extensions/erc20.d.ts.map +1 -1
- package/dist/types/exports/extensions/thirdweb.d.ts +15 -0
- package/dist/types/exports/extensions/thirdweb.d.ts.map +1 -0
- package/dist/types/exports/extensions/vote.d.ts +6 -0
- package/dist/types/exports/extensions/vote.d.ts.map +1 -1
- package/dist/types/exports/react.d.ts +4 -0
- package/dist/types/exports/react.d.ts.map +1 -1
- package/dist/types/extensions/prebuilts/deploy-split.d.ts +2 -1
- package/dist/types/extensions/prebuilts/deploy-split.d.ts.map +1 -1
- package/dist/types/extensions/vote/read/canExecute.d.ts +17 -0
- package/dist/types/extensions/vote/read/canExecute.d.ts.map +1 -0
- package/dist/types/extensions/vote/read/getAll.d.ts +64 -0
- package/dist/types/extensions/vote/read/getAll.d.ts.map +1 -0
- package/dist/types/extensions/vote/read/getProposalVoteCounts.d.ts +27 -0
- package/dist/types/extensions/vote/read/getProposalVoteCounts.d.ts.map +1 -0
- package/dist/types/extensions/vote/read/proposalExists.d.ts +17 -0
- package/dist/types/extensions/vote/read/proposalExists.d.ts.map +1 -0
- package/dist/types/extensions/vote/types.d.ts +16 -0
- package/dist/types/extensions/vote/types.d.ts.map +1 -0
- package/dist/types/extensions/vote/write/executeProposal.d.ts +25 -0
- package/dist/types/extensions/vote/write/executeProposal.d.ts.map +1 -0
- package/dist/types/react/core/utils/wallet.d.ts.map +1 -1
- package/dist/types/react/web/ui/ConnectWallet/Blobbie.d.ts +12 -0
- package/dist/types/react/web/ui/ConnectWallet/Blobbie.d.ts.map +1 -0
- package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/auth/verify-hash.ts +33 -0
- package/src/exports/extensions/erc20.ts +8 -0
- package/src/exports/extensions/thirdweb.ts +75 -0
- package/src/exports/extensions/vote.ts +14 -0
- package/src/exports/react.ts +5 -0
- package/src/extensions/prebuilts/deploy-split.ts +2 -1
- package/src/extensions/split/read/getAllRecipientsAddresses.test.ts +2 -0
- package/src/extensions/split/read/getAllRecipientsPercentages.test.ts +2 -0
- package/src/extensions/split/read/getRecipientSplitPercentage.test.ts +2 -0
- package/src/extensions/vote/read/canExecute.ts +27 -0
- package/src/extensions/vote/read/getAll.ts +106 -0
- package/src/extensions/vote/read/getProposalVoteCounts.ts +39 -0
- package/src/extensions/vote/read/proposalExists.ts +27 -0
- package/src/extensions/vote/types.ts +16 -0
- package/src/extensions/vote/write/executeProposal.ts +63 -0
- package/src/react/core/utils/wallet.ts +2 -2
- package/src/react/web/ui/ConnectWallet/Blobbie.tsx +134 -0
- package/src/react/web/ui/ConnectWallet/ConnectButton.tsx +8 -8
- package/src/react/web/ui/ConnectWallet/Details.tsx +54 -44
- package/src/react/web/ui/ConnectWallet/locale/en.ts +2 -2
- package/src/react/web/ui/TransactionButton/index.tsx +1 -1
- package/src/version.ts +1 -1
- package/src/wallets/smart/smart-wallet-zksync.test.ts +28 -1
package/src/auth/verify-hash.ts
CHANGED
@@ -8,6 +8,8 @@ import {
|
|
8
8
|
} from "viem";
|
9
9
|
import type { Chain } from "../chains/types.js";
|
10
10
|
import type { ThirdwebClient } from "../client/client.js";
|
11
|
+
import { type ThirdwebContract, getContract } from "../contract/contract.js";
|
12
|
+
import { isValidSignature } from "../extensions/erc1271/__generated__/isValidSignature/read/isValidSignature.js";
|
11
13
|
import { eth_call } from "../rpc/actions/eth_call.js";
|
12
14
|
import { getRpcClient } from "../rpc/rpc.js";
|
13
15
|
import { fromBytes } from "../utils/encoding/from-bytes.js";
|
@@ -110,8 +112,39 @@ export async function verifyHash({
|
|
110
112
|
const hexResult = isHex(result) ? toBytes(result) : result;
|
111
113
|
return equalBytes(hexResult, toBytes("0x1"));
|
112
114
|
} catch (error) {
|
115
|
+
// Some chains do not support the eth_call simulation and will fail, so we fall back to regular EIP1271 validation
|
116
|
+
const validEip1271 = await verifyEip1271Signature({
|
117
|
+
hash,
|
118
|
+
signature: signatureHex,
|
119
|
+
contract: getContract({
|
120
|
+
chain,
|
121
|
+
address,
|
122
|
+
client,
|
123
|
+
}),
|
124
|
+
}).catch(() => false);
|
125
|
+
if (validEip1271) {
|
126
|
+
return true;
|
127
|
+
}
|
113
128
|
// TODO: Improve overall RPC error handling so we can tell if this was an actual verification failure or some other error
|
114
129
|
// Verification failed somehow
|
115
130
|
return false;
|
116
131
|
}
|
117
132
|
}
|
133
|
+
|
134
|
+
const EIP_1271_MAGIC_VALUE = "0x1626ba7e";
|
135
|
+
async function verifyEip1271Signature({
|
136
|
+
hash,
|
137
|
+
signature,
|
138
|
+
contract,
|
139
|
+
}: {
|
140
|
+
hash: Hex;
|
141
|
+
signature: Hex;
|
142
|
+
contract: ThirdwebContract;
|
143
|
+
}): Promise<boolean> {
|
144
|
+
const result = await isValidSignature({
|
145
|
+
hash,
|
146
|
+
signature,
|
147
|
+
contract,
|
148
|
+
});
|
149
|
+
return result === EIP_1271_MAGIC_VALUE;
|
150
|
+
}
|
@@ -10,6 +10,10 @@ export {
|
|
10
10
|
type BalanceOfParams,
|
11
11
|
} from "../../extensions/erc20/__generated__/IERC20/read/balanceOf.js";
|
12
12
|
export { decimals } from "../../extensions/erc20/read/decimals.js";
|
13
|
+
export {
|
14
|
+
delegates,
|
15
|
+
type DelegatesParams,
|
16
|
+
} from "../../extensions/erc20/__generated__/IVotes/read/delegates.js";
|
13
17
|
export { totalSupply } from "../../extensions/erc20/__generated__/IERC20/read/totalSupply.js";
|
14
18
|
export {
|
15
19
|
allowance,
|
@@ -113,3 +117,7 @@ export {
|
|
113
117
|
getApprovalForTransaction,
|
114
118
|
type GetApprovalForTransactionParams,
|
115
119
|
} from "../../extensions/erc20/write/getApprovalForTransaction.js";
|
120
|
+
export {
|
121
|
+
delegate,
|
122
|
+
type DelegateParams,
|
123
|
+
} from "../../extensions/erc20/__generated__/IVotes/write/delegate.js";
|
@@ -0,0 +1,75 @@
|
|
1
|
+
// --------------------------------------------------------
|
2
|
+
// Publisher contract
|
3
|
+
// --------------------------------------------------------
|
4
|
+
|
5
|
+
// Read
|
6
|
+
export {
|
7
|
+
getPublisherProfileUri,
|
8
|
+
type GetPublisherProfileUriParams,
|
9
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/read/getPublisherProfileUri.js";
|
10
|
+
export {
|
11
|
+
getPublishedUriFromCompilerUri,
|
12
|
+
type GetPublishedUriFromCompilerUriParams,
|
13
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/read/getPublishedUriFromCompilerUri.js";
|
14
|
+
export {
|
15
|
+
getAllPublishedContracts,
|
16
|
+
type GetAllPublishedContractsParams,
|
17
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/read/getAllPublishedContracts.js";
|
18
|
+
export {
|
19
|
+
getPublishedContract,
|
20
|
+
type GetPublishedContractParams,
|
21
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/read/getPublishedContract.js";
|
22
|
+
export {
|
23
|
+
getPublishedContractVersions,
|
24
|
+
type GetPublishedContractVersionsParams,
|
25
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/read/getPublishedContractVersions.js";
|
26
|
+
|
27
|
+
// Write
|
28
|
+
export {
|
29
|
+
publishContract,
|
30
|
+
type PublishContractParams,
|
31
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/write/publishContract.js";
|
32
|
+
export {
|
33
|
+
setPublisherProfileUri,
|
34
|
+
type SetPublisherProfileUriParams,
|
35
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/write/setPublisherProfileUri.js";
|
36
|
+
export {
|
37
|
+
unpublishContract,
|
38
|
+
type UnpublishContractParams,
|
39
|
+
} from "../../extensions/thirdweb/__generated__/IContractPublisher/write/unpublishContract.js";
|
40
|
+
|
41
|
+
// --------------------------------------------------------
|
42
|
+
// Multichain Registry
|
43
|
+
// --------------------------------------------------------
|
44
|
+
|
45
|
+
// Read
|
46
|
+
export {
|
47
|
+
count,
|
48
|
+
type CountParams,
|
49
|
+
} from "../../extensions/thirdweb/__generated__/ITWMultichainRegistry/read/count.js";
|
50
|
+
export {
|
51
|
+
getAll,
|
52
|
+
type GetAllParams,
|
53
|
+
} from "../../extensions/thirdweb/__generated__/ITWMultichainRegistry/read/getAll.js";
|
54
|
+
export {
|
55
|
+
getMetadataUri,
|
56
|
+
type GetMetadataUriParams,
|
57
|
+
} from "../../extensions/thirdweb/__generated__/ITWMultichainRegistry/read/getMetadataUri.js";
|
58
|
+
|
59
|
+
// Write
|
60
|
+
export {
|
61
|
+
add,
|
62
|
+
type AddParams,
|
63
|
+
} from "../../extensions/thirdweb/__generated__/ITWMultichainRegistry/write/add.js";
|
64
|
+
export {
|
65
|
+
remove,
|
66
|
+
type RemoveParams,
|
67
|
+
} from "../../extensions/thirdweb/__generated__/ITWMultichainRegistry/write/remove.js";
|
68
|
+
|
69
|
+
// --------------------------------------------------------
|
70
|
+
// Contract Factory
|
71
|
+
// --------------------------------------------------------
|
72
|
+
export {
|
73
|
+
deployProxyByImplementation,
|
74
|
+
type DeployProxyByImplementationParams,
|
75
|
+
} from "../../extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementation.js";
|
@@ -67,6 +67,19 @@ export { votingDelay } from "../../extensions/vote/__generated__/Vote/read/votin
|
|
67
67
|
|
68
68
|
export { votingPeriod } from "../../extensions/vote/__generated__/Vote/read/votingPeriod.js";
|
69
69
|
|
70
|
+
export { proposalExists } from "../../extensions/vote/read/proposalExists.js";
|
71
|
+
|
72
|
+
export { VoteType, ProposalState } from "../../extensions/vote/types.js";
|
73
|
+
|
74
|
+
export { getProposalVoteCounts } from "../../extensions/vote/read/getProposalVoteCounts.js";
|
75
|
+
|
76
|
+
export {
|
77
|
+
getAll,
|
78
|
+
type ProposalItem,
|
79
|
+
} from "../../extensions/vote/read/getAll.js";
|
80
|
+
|
81
|
+
export { canExecute } from "../../extensions/vote/read/canExecute.js";
|
82
|
+
|
70
83
|
/**
|
71
84
|
* WRITE Methods
|
72
85
|
*/
|
@@ -129,3 +142,4 @@ export {
|
|
129
142
|
updateQuorumNumerator,
|
130
143
|
type UpdateQuorumNumeratorParams,
|
131
144
|
} from "../../extensions/vote/__generated__/Vote/write/updateQuorumNumerator.js";
|
145
|
+
export { executeProposal } from "../../extensions/vote/write/executeProposal.js";
|
package/src/exports/react.ts
CHANGED
@@ -172,3 +172,8 @@ export {
|
|
172
172
|
} from "../react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.js";
|
173
173
|
|
174
174
|
export { useConnectionManager } from "../react/core/providers/connection-manager.js";
|
175
|
+
|
176
|
+
/**
|
177
|
+
* Blobbie
|
178
|
+
*/
|
179
|
+
export { Blobbie } from "../react/web/ui/ConnectWallet/Blobbie.js";
|
@@ -9,7 +9,7 @@ import type { ClientAndChainAndAccount } from "../../utils/types.js";
|
|
9
9
|
import { initialize } from "./__generated__/Split/write/initialize.js";
|
10
10
|
|
11
11
|
/**
|
12
|
-
* @extension
|
12
|
+
* @extension DEPLOY
|
13
13
|
*/
|
14
14
|
export type SplitContractParams = {
|
15
15
|
name: string;
|
@@ -71,6 +71,7 @@ export type DeploySplitContractOptions = Prettify<
|
|
71
71
|
* name: "Split contract",
|
72
72
|
* payees: ["0x...123", "0x...456"],
|
73
73
|
* shares: [5100, 4900], // See type `SplitContractParams` for more context
|
74
|
+
* },
|
74
75
|
* });
|
75
76
|
* ```
|
76
77
|
*/
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
2
2
|
import { ANVIL_CHAIN } from "~test/chains.js";
|
3
|
+
import { TEST_CONTRACT_URI } from "~test/ipfs-uris.js";
|
3
4
|
import { TEST_CLIENT } from "~test/test-clients.js";
|
4
5
|
import { TEST_ACCOUNT_A } from "~test/test-wallets.js";
|
5
6
|
import { getContract } from "../../../contract/contract.js";
|
@@ -21,6 +22,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getAllRecipientsAddresses", () => {
|
|
21
22
|
chain: ANVIL_CHAIN,
|
22
23
|
params: {
|
23
24
|
name: "split-contract",
|
25
|
+
contractURI: TEST_CONTRACT_URI, // just to speed up the test
|
24
26
|
payees,
|
25
27
|
shares: [
|
26
28
|
5100n, // 51%
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
2
2
|
import { ANVIL_CHAIN } from "~test/chains.js";
|
3
|
+
import { TEST_CONTRACT_URI } from "~test/ipfs-uris.js";
|
3
4
|
import { TEST_CLIENT } from "~test/test-clients.js";
|
4
5
|
import { TEST_ACCOUNT_A } from "~test/test-wallets.js";
|
5
6
|
import { getContract } from "../../../contract/contract.js";
|
@@ -21,6 +22,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getAllRecipientsPercentages", () => {
|
|
21
22
|
chain: ANVIL_CHAIN,
|
22
23
|
params: {
|
23
24
|
name: "split-contract",
|
25
|
+
contractURI: TEST_CONTRACT_URI, // just to speed up the test
|
24
26
|
payees,
|
25
27
|
shares: [
|
26
28
|
5100n, // 51%
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
2
2
|
import { ANVIL_CHAIN } from "~test/chains.js";
|
3
|
+
import { TEST_CONTRACT_URI } from "~test/ipfs-uris.js";
|
3
4
|
import { TEST_CLIENT } from "~test/test-clients.js";
|
4
5
|
import { TEST_ACCOUNT_A } from "~test/test-wallets.js";
|
5
6
|
import { getContract } from "../../../contract/contract.js";
|
@@ -20,6 +21,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getRecipientSplitPercentage", () => {
|
|
20
21
|
chain: ANVIL_CHAIN,
|
21
22
|
params: {
|
22
23
|
name: "split-contract",
|
24
|
+
contractURI: TEST_CONTRACT_URI, // just to speed up the test
|
23
25
|
payees,
|
24
26
|
shares: [
|
25
27
|
5100n, // 51%
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { simulateTransaction } from "../../../transaction/actions/simulate.js";
|
2
|
+
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
3
|
+
import { executeProposal } from "../write/executeProposal.js";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Simulate the `execute` method of the Vote contract, to check if you can execute a proposal
|
7
|
+
* @extension VOTE
|
8
|
+
* @returns boolean - `true` if the proposal is executable, else `false`
|
9
|
+
*
|
10
|
+
* @example
|
11
|
+
* ```ts
|
12
|
+
* import { canExecute } from "thirdweb/extensions/vote";
|
13
|
+
*
|
14
|
+
* const executable = await canExecute({ contract, proposalId });
|
15
|
+
* ```
|
16
|
+
*/
|
17
|
+
export async function canExecute(
|
18
|
+
options: BaseTransactionOptions<{ proposalId: bigint }>,
|
19
|
+
) {
|
20
|
+
try {
|
21
|
+
const transaction = await executeProposal(options);
|
22
|
+
await simulateTransaction({ transaction });
|
23
|
+
return true;
|
24
|
+
} catch {
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
2
|
+
import type { Hex } from "../../../utils/encoding/hex.js";
|
3
|
+
import { getAllProposals } from "../__generated__/Vote/read/getAllProposals.js";
|
4
|
+
import { state } from "../__generated__/Vote/read/state.js";
|
5
|
+
import { ProposalState } from "../types.js";
|
6
|
+
import {
|
7
|
+
type ProposalVoteInfo,
|
8
|
+
getProposalVoteCounts,
|
9
|
+
} from "./getProposalVoteCounts.js";
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @extension VOTE
|
13
|
+
*/
|
14
|
+
export type ProposalItem = {
|
15
|
+
/**
|
16
|
+
* ID of the proposal
|
17
|
+
*/
|
18
|
+
proposalId: bigint;
|
19
|
+
/**
|
20
|
+
* The wallet address of the proposer
|
21
|
+
*/
|
22
|
+
proposer: string;
|
23
|
+
/**
|
24
|
+
* Description of the proposal
|
25
|
+
*/
|
26
|
+
description: string;
|
27
|
+
/**
|
28
|
+
* The block number at which the proposal is open for voting
|
29
|
+
*/
|
30
|
+
startBlock: bigint;
|
31
|
+
/**
|
32
|
+
* The block number where the proposal concludes its voting phase
|
33
|
+
*/
|
34
|
+
endBlock: bigint;
|
35
|
+
/**
|
36
|
+
* The current state of the proposal, represented in number
|
37
|
+
*/
|
38
|
+
state: number;
|
39
|
+
/**
|
40
|
+
* The current state of the proposal, represented in a user-friendly string
|
41
|
+
* Example: "pending" | "active" | "canceled"
|
42
|
+
*/
|
43
|
+
stateLabel: string | undefined;
|
44
|
+
/**
|
45
|
+
* The current vote info. See type ProposalVoteInfo for more context
|
46
|
+
*/
|
47
|
+
votes: ProposalVoteInfo;
|
48
|
+
/**
|
49
|
+
* The array of containing info about the set of actions that will be executed onchain,
|
50
|
+
* should the proposal pass
|
51
|
+
*/
|
52
|
+
executions: Array<{
|
53
|
+
toAddress: string | undefined;
|
54
|
+
nativeTokenValue: bigint | undefined;
|
55
|
+
transactionData: Hex | undefined;
|
56
|
+
}>;
|
57
|
+
};
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Get all proposals from a Vote contract with some extra info attached for each proposal (current state and votes)
|
61
|
+
* @extension VOTE
|
62
|
+
* @returns An array containing proposals data
|
63
|
+
*
|
64
|
+
* @example
|
65
|
+
* ```ts
|
66
|
+
* import { getAll } from "thirdweb/extension/getAll";
|
67
|
+
*
|
68
|
+
* const allProposals = await getAll({ contract });
|
69
|
+
* ```
|
70
|
+
*/
|
71
|
+
export async function getAll(
|
72
|
+
options: BaseTransactionOptions,
|
73
|
+
): Promise<ProposalItem[]> {
|
74
|
+
const _proposals = await getAllProposals(options);
|
75
|
+
const _extraData = await Promise.all(
|
76
|
+
_proposals.map((proposal) => {
|
77
|
+
const params = {
|
78
|
+
contract: options.contract,
|
79
|
+
proposalId: proposal.proposalId,
|
80
|
+
};
|
81
|
+
return Promise.all([state(params), getProposalVoteCounts(params)]);
|
82
|
+
}),
|
83
|
+
);
|
84
|
+
return _extraData.map(([state, votes], index) => {
|
85
|
+
const data = _proposals[index];
|
86
|
+
// We know `data` SHOULD exist but adding the error-throw below to make typescript happy
|
87
|
+
if (!data) {
|
88
|
+
throw new Error(`Proposal not found for index: ${index}`);
|
89
|
+
}
|
90
|
+
return {
|
91
|
+
proposalId: data.proposalId,
|
92
|
+
proposer: data.proposer,
|
93
|
+
description: data.description,
|
94
|
+
startBlock: data.startBlock,
|
95
|
+
endBlock: data.endBlock,
|
96
|
+
state: state,
|
97
|
+
stateLabel: ProposalState[state],
|
98
|
+
votes: votes,
|
99
|
+
executions: data.targets.map((_, index) => ({
|
100
|
+
toAddress: data.targets[index],
|
101
|
+
nativeTokenValue: data.values[index],
|
102
|
+
transactionData: data.calldatas[index],
|
103
|
+
})),
|
104
|
+
};
|
105
|
+
});
|
106
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
2
|
+
import {
|
3
|
+
type ProposalVotesParams,
|
4
|
+
proposalVotes,
|
5
|
+
} from "../__generated__/Vote/read/proposalVotes.js";
|
6
|
+
import type { VoteType } from "../types.js";
|
7
|
+
|
8
|
+
// @internal
|
9
|
+
export type ProposalVoteInfo = { [K in keyof typeof VoteType]: bigint };
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Get the info about Against, For and Abstain votes of a proposal
|
13
|
+
* @param options
|
14
|
+
* @returns the object containing the info about Against, For and Abstain votes of a proposal
|
15
|
+
* @extension VOTE
|
16
|
+
* @example
|
17
|
+
* ```ts
|
18
|
+
* import { getProposalVoteCounts } from "thirdweb/extensions/vote";
|
19
|
+
*
|
20
|
+
* const data = await getProposalVoteCounts({ contract, proposalId });
|
21
|
+
*
|
22
|
+
* // Example result
|
23
|
+
* {
|
24
|
+
* against: 12n, // 12 users voted against the proposal
|
25
|
+
* for: 104n, // 104 users support the proposal
|
26
|
+
* abstain: 3n, // 3 users voted abstain on this proposal
|
27
|
+
* }
|
28
|
+
* ```
|
29
|
+
*/
|
30
|
+
export async function getProposalVoteCounts(
|
31
|
+
options: BaseTransactionOptions<ProposalVotesParams>,
|
32
|
+
): Promise<ProposalVoteInfo> {
|
33
|
+
const votes = await proposalVotes(options);
|
34
|
+
return {
|
35
|
+
against: votes[0],
|
36
|
+
for: votes[1],
|
37
|
+
abstain: votes[2],
|
38
|
+
};
|
39
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
2
|
+
import { type StateParams, state } from "../__generated__/Vote/read/state.js";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Check if a proposal exists based on a given proposalId
|
6
|
+
* @returns `true` if the proposal exists, else `false`
|
7
|
+
* @extension VOTE
|
8
|
+
*
|
9
|
+
* @example
|
10
|
+
* ```ts
|
11
|
+
* import { proposalExists } from "thirdweb/extensions/vote";
|
12
|
+
*
|
13
|
+
* // Check if the proposal with proposalId `4` exists
|
14
|
+
* const exists = await proposalExists({ contract, proposalId: 4n }); // either `true` or `false`
|
15
|
+
* ```
|
16
|
+
*/
|
17
|
+
export async function proposalExists(
|
18
|
+
options: BaseTransactionOptions<StateParams>,
|
19
|
+
) {
|
20
|
+
try {
|
21
|
+
await state(options);
|
22
|
+
return true;
|
23
|
+
} catch (e) {
|
24
|
+
// If it throws an error then the proposal(id) doesn't exist
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
2
|
+
import {
|
3
|
+
type ExecuteParams,
|
4
|
+
execute,
|
5
|
+
} from "../__generated__/Vote/write/execute.js";
|
6
|
+
import { proposalExists } from "../read/proposalExists.js";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Execute a Proposal
|
10
|
+
* @extension VOTE
|
11
|
+
* @returns a prepared transaction for the `execute` method
|
12
|
+
*
|
13
|
+
* @example
|
14
|
+
* ```ts
|
15
|
+
* import { executeProposal } from "thirdweb/extensions/vote";
|
16
|
+
*
|
17
|
+
* const transaction = executeProposal({ contract, proposalId });
|
18
|
+
* const tx = await sendTransaction({ transaction, account });
|
19
|
+
* ```
|
20
|
+
*/
|
21
|
+
export function executeProposal(
|
22
|
+
options: BaseTransactionOptions<{ proposalId: bigint }>,
|
23
|
+
) {
|
24
|
+
return execute({
|
25
|
+
contract: options.contract,
|
26
|
+
asyncParams: async () => getExecuteParams(options),
|
27
|
+
});
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* @internal
|
32
|
+
*/
|
33
|
+
export async function getExecuteParams(
|
34
|
+
options: BaseTransactionOptions<{ proposalId: bigint }>,
|
35
|
+
): Promise<ExecuteParams> {
|
36
|
+
const { proposalId } = options;
|
37
|
+
const exists = await proposalExists(options);
|
38
|
+
if (!exists) {
|
39
|
+
throw new Error(`Proposal ID: ${proposalId} does not exists`);
|
40
|
+
}
|
41
|
+
const [{ getAllProposals }, { keccak256 }, { stringToBytes }] =
|
42
|
+
await Promise.all([
|
43
|
+
import("../__generated__/Vote/read/getAllProposals.js"),
|
44
|
+
import("../../../utils/hashing/keccak256.js"),
|
45
|
+
import("../../../utils/encoding/to-bytes.js"),
|
46
|
+
import("../__generated__/Vote/write/execute.js"),
|
47
|
+
]);
|
48
|
+
|
49
|
+
// Sadly there isn't a way to fetch a single proposal so we have to load them all
|
50
|
+
const _proposals = await getAllProposals(options);
|
51
|
+
const proposal = _proposals.find((p) => p.proposalId === proposalId);
|
52
|
+
if (!proposal) {
|
53
|
+
throw new Error(`Could not find proposalId: ${proposalId}`);
|
54
|
+
}
|
55
|
+
const { targets, values, calldatas, description } = proposal;
|
56
|
+
const descriptionHash = keccak256(stringToBytes(description));
|
57
|
+
return {
|
58
|
+
descriptionHash,
|
59
|
+
targets,
|
60
|
+
values,
|
61
|
+
calldatas,
|
62
|
+
};
|
63
|
+
}
|
@@ -4,12 +4,12 @@ import type { Chain } from "../../../chains/types.js";
|
|
4
4
|
import type { ThirdwebClient } from "../../../client/client.js";
|
5
5
|
import { resolveAvatar } from "../../../extensions/ens/resolve-avatar.js";
|
6
6
|
import { resolveName } from "../../../extensions/ens/resolve-name.js";
|
7
|
+
import { shortenAddress } from "../../../utils/address.js";
|
7
8
|
import { getWalletInfo } from "../../../wallets/__generated__/getWalletInfo.js";
|
8
9
|
import type { Account, Wallet } from "../../../wallets/interfaces/wallet.js";
|
9
10
|
import type { WalletInfo } from "../../../wallets/wallet-info.js";
|
10
11
|
import type { WalletId } from "../../../wallets/wallet-types.js";
|
11
12
|
import { useWalletBalance } from "../hooks/others/useWalletBalance.js";
|
12
|
-
import { shortenString } from "./addresses.js";
|
13
13
|
|
14
14
|
/**
|
15
15
|
* Get the ENS name and avatar for an address
|
@@ -99,7 +99,7 @@ export function useConnectedWalletDetails(
|
|
99
99
|
});
|
100
100
|
|
101
101
|
const shortAddress = activeAccount?.address
|
102
|
-
?
|
102
|
+
? shortenAddress(activeAccount.address, 4)
|
103
103
|
: "";
|
104
104
|
|
105
105
|
const balanceQuery = useWalletBalance({
|
@@ -0,0 +1,134 @@
|
|
1
|
+
"use client";
|
2
|
+
import { hexToNumber } from "@noble/curves/abstract/utils";
|
3
|
+
import { useId, useMemo } from "react";
|
4
|
+
import { type Address, numberToHex } from "viem";
|
5
|
+
|
6
|
+
// Distance between 2 colors (in RGB)
|
7
|
+
type Color = [number, number, number];
|
8
|
+
function hexToRgb(hex: string) {
|
9
|
+
return [
|
10
|
+
Number(hexToNumber(hex.slice(0, 2))),
|
11
|
+
Number(hexToNumber(hex.slice(2, 4))),
|
12
|
+
Number(hexToNumber(hex.slice(4, 6))),
|
13
|
+
] satisfies [number, number, number];
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* A unique gradient avatar based on the provided address.
|
18
|
+
* @param props The component props.
|
19
|
+
* @param props.address The address to generate the gradient with.
|
20
|
+
* @param props.size The size of each side of the square avatar (in pixels)
|
21
|
+
*/
|
22
|
+
export function Blobbie(props: { address: Address; size: number }) {
|
23
|
+
const id = useId();
|
24
|
+
const colors: [string, string, string] = useMemo(() => {
|
25
|
+
const color = props.address.slice(2, 8);
|
26
|
+
const rgb = hexToRgb(color);
|
27
|
+
|
28
|
+
// To get well-paired colors, we use the first rgb hex sequence as our main color then find its two best pairs (split color wheel into thirds)
|
29
|
+
// To prevent extremely dark colors, which tend to clash, we don't allow values less than 55
|
30
|
+
const pairing1 = rgb.map((n) => (n + 85 > 255 ? n + 85 - 200 : n + 85));
|
31
|
+
const pairing2 = rgb.map((n) => (n - 85 < 55 ? n - 85 + 200 : n - 85));
|
32
|
+
return [
|
33
|
+
color,
|
34
|
+
pairing1.map((n) => numberToHex(n).replace("0x", "")).join(""),
|
35
|
+
pairing2.map((n) => numberToHex(n).replace("0x", "")).join(""),
|
36
|
+
];
|
37
|
+
}, [props.address]);
|
38
|
+
|
39
|
+
const positions: [Color, Color, Color, Color, Color] = useMemo(() => {
|
40
|
+
const _positions: Color[] = [];
|
41
|
+
let i = 8;
|
42
|
+
while (i < 44) {
|
43
|
+
const values = hexToRgb(props.address.slice(i, i + 6));
|
44
|
+
_positions.push(values);
|
45
|
+
i += 6;
|
46
|
+
}
|
47
|
+
return _positions as [Color, Color, Color, Color, Color];
|
48
|
+
}, [props.address]);
|
49
|
+
|
50
|
+
console.log(colors);
|
51
|
+
|
52
|
+
return (
|
53
|
+
<svg
|
54
|
+
height={`${props.size}px`}
|
55
|
+
style={{ background: "#FFFFFF" }}
|
56
|
+
width={`${props.size}px`}
|
57
|
+
role="presentation"
|
58
|
+
viewBox="0 0 500 500"
|
59
|
+
xmlns="http://www.w3.org/2000/svg"
|
60
|
+
>
|
61
|
+
<defs>
|
62
|
+
{colors.map((color, idx) => {
|
63
|
+
return (
|
64
|
+
<radialGradient
|
65
|
+
id={`${id}_grad${idx + 1}`}
|
66
|
+
cx="50%"
|
67
|
+
cy="50%"
|
68
|
+
r="50%"
|
69
|
+
key={`grad${
|
70
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: Jonas said so
|
71
|
+
idx
|
72
|
+
}`}
|
73
|
+
>
|
74
|
+
<stop
|
75
|
+
offset="0%"
|
76
|
+
style={{ stopColor: `#${color}`, stopOpacity: 0.9 }}
|
77
|
+
/>
|
78
|
+
<stop
|
79
|
+
offset="100%"
|
80
|
+
style={{ stopColor: `#${color}`, stopOpacity: 0 }}
|
81
|
+
/>
|
82
|
+
</radialGradient>
|
83
|
+
);
|
84
|
+
})}
|
85
|
+
</defs>
|
86
|
+
|
87
|
+
<ellipse
|
88
|
+
cx="250"
|
89
|
+
cy="250"
|
90
|
+
rx="500"
|
91
|
+
ry="500"
|
92
|
+
fill={`url(#${id}_grad1)`}
|
93
|
+
opacity={0.5}
|
94
|
+
/>
|
95
|
+
<ellipse
|
96
|
+
cx={400 + positions[0][0]}
|
97
|
+
cy={400 + positions[0][1]}
|
98
|
+
rx={350 + positions[0][2]}
|
99
|
+
ry={350 + positions[0][2]}
|
100
|
+
fill={`url(#${id}_grad1)`}
|
101
|
+
/>
|
102
|
+
<ellipse
|
103
|
+
cx={positions[1][0]}
|
104
|
+
cy={positions[1][1]}
|
105
|
+
rx={350 + positions[1][2]}
|
106
|
+
ry={350 + positions[1][2]}
|
107
|
+
fill={`url(#${id}_grad2)`}
|
108
|
+
/>
|
109
|
+
<ellipse
|
110
|
+
cx={400 + positions[2][0]}
|
111
|
+
cy={positions[2][1]}
|
112
|
+
rx={350 + positions[2][2]}
|
113
|
+
ry={350 + positions[2][2]}
|
114
|
+
fill={`url(#${id}_grad3)`}
|
115
|
+
/>
|
116
|
+
<ellipse
|
117
|
+
cx={positions[3][0]}
|
118
|
+
cy={positions[3][1]}
|
119
|
+
rx={100 + positions[3][2]}
|
120
|
+
ry={100 + positions[3][2]}
|
121
|
+
fill={`url(#${id}_grad2)`}
|
122
|
+
opacity={0.5}
|
123
|
+
/>
|
124
|
+
<ellipse
|
125
|
+
cx={positions[4][0]}
|
126
|
+
cy={positions[4][1]}
|
127
|
+
rx={100 + positions[4][2]}
|
128
|
+
ry={100 + positions[4][2]}
|
129
|
+
fill={`url(#${id}_grad3)`}
|
130
|
+
opacity={0.5}
|
131
|
+
/>
|
132
|
+
</svg>
|
133
|
+
);
|
134
|
+
}
|