Compare commits

..
Author SHA1 Message Date
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
30 changed files with 523 additions and 173 deletions
+14
View File
@@ -1,5 +1,19 @@
# @thirdweb-dev/auth
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "4.0.3",
"version": "4.0.5",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+18
View File
@@ -1,5 +1,23 @@
# thirdweb
## 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
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.13.3",
"version": "0.13.5",
"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",
+18
View File
@@ -1,5 +1,23 @@
# @thirdweb-dev/react-core
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "4.0.3",
"version": "4.0.5",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -1,5 +1,9 @@
# @thirdweb-dev/react-native-compat
## 0.3.10
## 0.3.9
## 0.3.8
## 0.3.7
+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.8",
"version": "0.3.10",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
"license": "Apache-2.0",
+18
View File
@@ -1,5 +1,23 @@
# @thirdweb-dev/react-native
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.3.8",
"version": "0.3.10",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+20
View File
@@ -1,5 +1,25 @@
# @thirdweb-dev/react
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "4.0.3",
"version": "4.0.5",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -38,7 +38,9 @@ export function OTPInput(props: {
key={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
+16
View File
@@ -1,5 +1,21 @@
# @thirdweb-dev/sdk
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "4.0.2",
"version": "4.0.4",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
@@ -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);
@@ -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;
+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(
+18
View File
@@ -1,5 +1,23 @@
# @thirdweb-dev/unity-js-bridge
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/unity-js-bridge",
"version": "0.2.89",
"version": "0.2.91",
"main": "dist/thirdweb-unity-bridge.js",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
"license": "Apache-2.0",
+16
View File
@@ -1,5 +1,21 @@
# @thirdweb-dev/wallets
## 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/wallets",
"version": "2.0.3",
"version": "2.0.5",
"main": "dist/thirdweb-dev-wallets.cjs.js",
"module": "dist/thirdweb-dev-wallets.esm.js",
"types": "dist/thirdweb-dev-wallets.cjs.d.ts",
+7 -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
@@ -12033,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
@@ -17545,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
@@ -25549,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