Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26367c04f3 | ||
|
|
39e2af6f2f | ||
|
|
a5ba9e4fbf |
@@ -1,5 +1,12 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 3.2.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/wallets@1.1.14
|
||||
|
||||
## 3.2.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "3.2.30",
|
||||
"version": "3.2.31",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Japan Open Chain Testnet",
|
||||
"chain": "JOCT",
|
||||
"rpc": [
|
||||
"https://japan-open-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc-1.testnet.japanopenchain.org:8545",
|
||||
"https://rpc-2.testnet.japanopenchain.org:8545"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Japan Open Chain Testnet Token",
|
||||
"symbol": "JOCT",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://www.japanopenchain.org/",
|
||||
"shortName": "joct",
|
||||
"chainId": 10081,
|
||||
"networkId": 10081,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Testnet Block Explorer",
|
||||
"url": "https://explorer.testnet.japanopenchain.org",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "japan-open-chain-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,5 +1,12 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.11.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/sdk@3.10.50
|
||||
|
||||
## 0.11.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.11.13",
|
||||
"version": "0.11.14",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 3.14.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74), [`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/wallets@1.1.14
|
||||
- @thirdweb-dev/sdk@3.10.50
|
||||
- @thirdweb-dev/auth@3.2.31
|
||||
|
||||
## 3.14.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "3.14.30",
|
||||
"version": "3.14.31",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.2.50
|
||||
|
||||
## 0.2.49
|
||||
|
||||
## 0.2.48
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.2.49",
|
||||
"version": "0.2.50",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.2.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74), [`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/wallets@1.1.14
|
||||
- @thirdweb-dev/sdk@3.10.50
|
||||
- @thirdweb-dev/react-core@3.14.31
|
||||
|
||||
## 0.2.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.2.49",
|
||||
"version": "0.2.50",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.14.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74), [`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/wallets@1.1.14
|
||||
- @thirdweb-dev/sdk@3.10.50
|
||||
- @thirdweb-dev/react-core@3.14.31
|
||||
|
||||
## 3.14.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.14.30",
|
||||
"version": "3.14.31",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.10.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1480](https://github.com/thirdweb-dev/js/pull/1480) [`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Separate Account and AccountPermissions extensions
|
||||
|
||||
- [#1484](https://github.com/thirdweb-dev/js/pull/1484) [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose getPolygonGasPriorityFee()
|
||||
|
||||
## 3.10.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.10.49",
|
||||
"version": "3.10.50",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from "./error";
|
||||
export * from "./snapshots";
|
||||
export * from "./role";
|
||||
export * from "./metadata-resolver";
|
||||
export * from "./gas-price";
|
||||
|
||||
// feature detection
|
||||
export * from "./feature-detection/matchesPrebuiltAbi";
|
||||
|
||||
@@ -67,6 +67,7 @@ import {
|
||||
FEATURE_EXTENSION_ROUTER,
|
||||
FEATURE_ACCOUNT,
|
||||
FEATURE_ACCOUNT_FACTORY,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
} from "./thirdweb-features";
|
||||
|
||||
/**
|
||||
@@ -134,6 +135,7 @@ export type Feature =
|
||||
| typeof FEATURE_ENGLISH_AUCTIONS
|
||||
| typeof FEATURE_OFFERS
|
||||
| typeof FEATURE_ACCOUNT
|
||||
| typeof FEATURE_ACCOUNT_PERMISSIONS
|
||||
| typeof FEATURE_ACCOUNT_FACTORY;
|
||||
|
||||
export type Extension = Feature;
|
||||
|
||||
@@ -12,7 +12,8 @@ import IThirdwebPrimarySaleAbi from "@thirdweb-dev/contracts-js/dist/abis/IPrima
|
||||
import IThirdwebRoyaltyAbi from "@thirdweb-dev/contracts-js/dist/abis/IRoyalty.json";
|
||||
import IOwnableAbi from "@thirdweb-dev/contracts-js/dist/abis/Ownable.json";
|
||||
import IAccountFactory from "@thirdweb-dev/contracts-js/dist/abis/IAccountFactory.json";
|
||||
import IAccountCore from "@thirdweb-dev/contracts-js/dist/abis/IAccountCore.json";
|
||||
import IAccountPermissions from "@thirdweb-dev/contracts-js/dist/abis/IAccountPermissions.json";
|
||||
import IAccount from "@thirdweb-dev/contracts-js/dist/abis/IAccount.json";
|
||||
|
||||
export const getAllPluginsAbi = [
|
||||
{
|
||||
@@ -291,6 +292,18 @@ export const FEATURE_ACCOUNT_FACTORY = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_ACCOUNT_PERMISSIONS = {
|
||||
name: "AccountPermissions",
|
||||
namespace: "accountPermissions",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "sdk.account",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAccountPermissions],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_ACCOUNT = {
|
||||
name: "Account",
|
||||
namespace: "account",
|
||||
@@ -299,6 +312,6 @@ export const FEATURE_ACCOUNT = {
|
||||
sdk: "sdk.account",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAccountCore],
|
||||
features: {},
|
||||
abis: [IAccount],
|
||||
features: { [FEATURE_ACCOUNT_PERMISSIONS.name]: FEATURE_ACCOUNT_PERMISSIONS },
|
||||
} as const;
|
||||
|
||||
@@ -0,0 +1,727 @@
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { FEATURE_ACCOUNT_PERMISSIONS } from "../../constants/thirdweb-features";
|
||||
import { utils, BigNumber } from "ethers";
|
||||
import { Transaction } from "./transactions";
|
||||
|
||||
import type {
|
||||
IAccountCore,
|
||||
IAccountPermissions,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import {
|
||||
SignedSignerPermissionsPayload,
|
||||
SignerPermissionsOutput,
|
||||
SignerWithPermissions,
|
||||
SignerPermissions,
|
||||
SignerPermissionsInput,
|
||||
SignerPermissionRequest,
|
||||
SignerPermissionsSchema,
|
||||
PermissionSnapshotInput,
|
||||
PermissionSnapshotSchema,
|
||||
PermissionSnapshotOutput,
|
||||
} from "../../types";
|
||||
import invariant from "tiny-invariant";
|
||||
import { buildTransactionFunction } from "../../common/transactions";
|
||||
import { resolveOrGenerateId } from "../../common/signature-minting";
|
||||
import { AddressOrEns } from "../../schema";
|
||||
import { resolveAddress } from "../../common";
|
||||
|
||||
export class AccountPermissions implements DetectableFeature {
|
||||
featureName = FEATURE_ACCOUNT_PERMISSIONS.name;
|
||||
private contractWrapper: ContractWrapper<IAccountCore>;
|
||||
|
||||
constructor(contractWrapper: ContractWrapper<IAccountCore>) {
|
||||
this.contractWrapper = contractWrapper;
|
||||
}
|
||||
|
||||
getAddress(): string {
|
||||
return this.contractWrapper.readContract.address;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* HELPER FUNCTIONS
|
||||
********************************/
|
||||
|
||||
private hasDuplicateSigners(snapshot: PermissionSnapshotOutput): boolean {
|
||||
const checkedSigner: Record<string, boolean> = {};
|
||||
|
||||
const signers = snapshot.map((item) => item.signer);
|
||||
|
||||
for (const signer of signers) {
|
||||
if (!checkedSigner[signer]) {
|
||||
checkedSigner[signer] = true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the access restrictions for a given role
|
||||
*
|
||||
* @param restrictions - The access restrictions for a given role
|
||||
* @returns formatted role restrictions
|
||||
*
|
||||
*/
|
||||
private parseSignerPermissionsStruct(
|
||||
permissions: IAccountPermissions.SignerPermissionsStruct,
|
||||
): SignerPermissions {
|
||||
return {
|
||||
startDate: new Date(
|
||||
parseInt(permissions.startTimestamp.toString()) * 1000,
|
||||
),
|
||||
expirationDate: new Date(
|
||||
parseInt(permissions.endTimestamp.toString()) * 1000,
|
||||
),
|
||||
nativeTokenLimitPerTransaction: BigNumber.from(
|
||||
permissions.nativeTokenLimitPerTransaction,
|
||||
),
|
||||
approvedCallTargets: permissions.approvedTargets,
|
||||
};
|
||||
}
|
||||
|
||||
private async sendSignerPermissionRequest(
|
||||
signerAddress: string,
|
||||
permissions: SignerPermissionsOutput,
|
||||
): Promise<Transaction> {
|
||||
const { payload, signature } = await this.generatePayload(
|
||||
signerAddress,
|
||||
permissions,
|
||||
);
|
||||
|
||||
const { success } =
|
||||
await this.contractWrapper.readContract.verifySignerPermissionRequest(
|
||||
payload,
|
||||
signature,
|
||||
);
|
||||
if (!success) {
|
||||
throw new Error(`Invalid signature.`);
|
||||
}
|
||||
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "setPermissionsForSigner",
|
||||
args: [payload, signature],
|
||||
});
|
||||
}
|
||||
|
||||
private async buildSignerPermissionRequest(
|
||||
signerAddress: string,
|
||||
permissions: SignerPermissionsOutput,
|
||||
): Promise<string> {
|
||||
const { payload, signature } = await this.generatePayload(
|
||||
signerAddress,
|
||||
permissions,
|
||||
);
|
||||
|
||||
const isValidSigner =
|
||||
await this.contractWrapper.readContract.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.
|
||||
*
|
||||
* @param signer - The address of the signer
|
||||
* @param roleAction - The address of the signer
|
||||
* @returns The generated payload and signature produced on signing that payload.
|
||||
*
|
||||
*/
|
||||
private async generatePayload(
|
||||
signerAddress: string,
|
||||
permissions: SignerPermissionsOutput,
|
||||
): Promise<SignedSignerPermissionsPayload> {
|
||||
// Get payload struct.
|
||||
const payload: IAccountPermissions.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),
|
||||
};
|
||||
|
||||
// Generate signature
|
||||
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 },
|
||||
payload,
|
||||
);
|
||||
|
||||
return { payload, signature };
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* READ FUNCTIONS
|
||||
********************************/
|
||||
|
||||
/**
|
||||
* Get whether a signer is an admin on the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const isAdmin = await contract.account.isAdmin(signer);
|
||||
* ```
|
||||
* @param signer - The address of a signer of the account.
|
||||
* @returns whether a signer is an admin on the account.
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async isAdmin(signerAddress: AddressOrEns): Promise<boolean> {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return await this.contractWrapper.readContract.isAdmin(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether a signer has permissions to use the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const isAdmin = await contract.account.isSigner(signer);
|
||||
* ```
|
||||
* @param signer - The address of a signer of the account.
|
||||
* @returns whether a signer has permissions to use the account.
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async isSigner(signerAddress: AddressOrEns): Promise<boolean> {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return await this.contractWrapper.readContract.isActiveSigner(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all admins of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allAdmins = await contract.account.getAllAdmins();
|
||||
* ```
|
||||
*
|
||||
* @returns all admins of the account.
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async getAllAdmins(): Promise<string[]> {
|
||||
return await this.contractWrapper.readContract.getAllAdmins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all (non-admin) signers with permissions to use the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allSigners = await contract.account.getAllSigners();
|
||||
* ```
|
||||
*
|
||||
* @returns all (non-admin) signers with permissions to use the account.
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async getAllSigners(): Promise<SignerWithPermissions[]> {
|
||||
const activeSignersWithPerms: IAccountPermissions.SignerPermissionsStruct[] =
|
||||
await this.contractWrapper.readContract.getAllActiveSigners();
|
||||
|
||||
return await Promise.all(
|
||||
activeSignersWithPerms.map(async (signerWithPermissions) => {
|
||||
const signer = signerWithPermissions.signer;
|
||||
const permissions = this.parseSignerPermissionsStruct(
|
||||
signerWithPermissions,
|
||||
);
|
||||
return { signer, permissions };
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all admins and non-admin signers with permissions to use the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allAdminsAndSigners = await contract.account.getAllAdminsAndSigners();
|
||||
* ```
|
||||
*
|
||||
* @returns all admins and non-admin signers with permissions to use the account.
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async getAllAdminsAndSigners(): Promise<SignerWithPermissions[]> {
|
||||
const allAdmins = await this.getAllAdmins();
|
||||
const transformedAdmins: SignerWithPermissions[] = allAdmins.map(
|
||||
(admin) => {
|
||||
return {
|
||||
isAdmin: true,
|
||||
signer: admin,
|
||||
permissions: {
|
||||
startDate: new Date(0),
|
||||
expirationDate: new Date(0),
|
||||
nativeTokenLimitPerTransaction: BigNumber.from(0),
|
||||
approvedCallTargets: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
);
|
||||
const allSigners = await this.getAllSigners();
|
||||
|
||||
return [...transformedAdmins, ...allSigners];
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* WRITE FUNCTIONS
|
||||
********************************/
|
||||
|
||||
/**
|
||||
* Grant an address admin access to the account.
|
||||
*
|
||||
* @remarks Grants an address admin access to the account. The admin will have complete authority over the account.
|
||||
*
|
||||
* @param signer - The address to be granted admin access to the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.grantAdminAccess(signer);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
grantAdminPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "setAdmin",
|
||||
args: [resolvedSignerAddress, true],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Revoke an address' admin access to the account.
|
||||
*
|
||||
* @remarks Revokes an address' admin access to the account.
|
||||
*
|
||||
* @param signer - The address of an admin of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.revokeAdminAccess(signer);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
revokeAdminPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "setAdmin",
|
||||
args: [resolvedSignerAddress, false],
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Grant a signer permissions to use the account.
|
||||
*
|
||||
* @remarks Grants a signer permissions to use the account.
|
||||
*
|
||||
* @param signer - The signer to be granted permissions to use the account.
|
||||
* @param permissions - The permissions to be applied to the signer's use of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.grantPermissions(signer, permissions);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
grantPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
permissions: SignerPermissionsInput,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedPermissions = await SignerPermissionsSchema.parseAsync(
|
||||
permissions,
|
||||
);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot grant permissions to an existing admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (await this.isSigner(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer already has permissions. Cannot grant permissions to an existing signer. You can update permissions using `updatePermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
return await this.sendSignerPermissionRequest(
|
||||
resolvedSignerAddress,
|
||||
resolvedPermissions,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Update the permissions of a signer for using the account.
|
||||
*
|
||||
* @remarks Updates the permissions of a signer for using the account.
|
||||
*
|
||||
* @param signer - The signer whose permissions to use the account are to be updated.
|
||||
* @param permissions - The permissions to be applied to the signer's use of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.updateAccess(signer, restrictions);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
updatePermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
permissions: SignerPermissionsInput,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedPermissions = await SignerPermissionsSchema.parseAsync(
|
||||
permissions,
|
||||
);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot update permissions of an existing admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
return await this.sendSignerPermissionRequest(
|
||||
resolvedSignerAddress,
|
||||
resolvedPermissions,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Revoke a scoped access address to the account
|
||||
*
|
||||
* @remarks Revokes an address' access to the account.
|
||||
*
|
||||
* @param signer - The address whose access to the account is to be revoked.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.revokeAccess(signer);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
revokeAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot revoke permissions of an admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
return await this.sendSignerPermissionRequest(resolvedSignerAddress, {
|
||||
startDate: BigNumber.from(0),
|
||||
expirationDate: BigNumber.from(0),
|
||||
approvedCallTargets: [],
|
||||
nativeTokenLimitPerTransaction: "0",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Approve an address as a call target for a given signer on the account
|
||||
*
|
||||
* @remarks Approves an address as a call target for a given signer on the account.
|
||||
*
|
||||
* @param signer - A signer with restricted access to the account.
|
||||
* @param target - The address to approve as a call target for the signer.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.approveTargetForSigner(signer, target);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
approveTargetForSigner = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
target: AddressOrEns,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedTarget = await resolveAddress(target);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot approve targets for an admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
const permissions: IAccountPermissions.SignerPermissionsStruct =
|
||||
await this.contractWrapper.readContract.getPermissionsForSigner(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
|
||||
if (permissions.approvedTargets.includes(target)) {
|
||||
throw new Error("Target is already approved");
|
||||
}
|
||||
|
||||
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(),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Disapprove an address as a call target for a given signer on the account
|
||||
*
|
||||
* @remarks Disapprove an address as a call target for a given signer on the account.
|
||||
*
|
||||
* @param signer - A signer with restricted access to the account.
|
||||
* @param target - The address to disapprove as a call target for the signer.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.disapproveTargetForSigner(signer, target);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
disapproveTargetForSigner = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
target: AddressOrEns,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedTarget = await resolveAddress(target);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot approve targets for an admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
const permissions: IAccountPermissions.SignerPermissionsStruct =
|
||||
await this.contractWrapper.readContract.getPermissionsForSigner(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
|
||||
if (!permissions.approvedTargets.includes(resolvedTarget)) {
|
||||
throw new Error("Target is currently not approved");
|
||||
}
|
||||
|
||||
const newTargets = permissions.approvedTargets.filter(
|
||||
(approvedTarget) =>
|
||||
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(),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the account's entire snapshot of permissions.
|
||||
*
|
||||
* @remarks Sets the account's entire snapshot of permissions.
|
||||
*
|
||||
* @param permissionSnapshot - the snapshot to set as the account's entire permission snapshot.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.account.setAccess(permissionSnapshot);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
resetAllPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
permissionSnapshot: PermissionSnapshotInput,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSnapshot = await PermissionSnapshotSchema.parseAsync(
|
||||
permissionSnapshot,
|
||||
);
|
||||
|
||||
/**
|
||||
* All cases
|
||||
*
|
||||
* - Add new admin :check:
|
||||
* - Remove current admin :check:
|
||||
* - Add new scoped :check:
|
||||
* - Remove current scoped :check:
|
||||
* - Update current scoped :check:
|
||||
* - Current admin -> new scoped :check:
|
||||
* - Current scoped -> new admin :check:
|
||||
**/
|
||||
|
||||
// No duplicate signers in input!
|
||||
if (this.hasDuplicateSigners(resolvedSnapshot)) {
|
||||
throw new Error("Duplicate signers found in input.");
|
||||
}
|
||||
|
||||
const addAdminData: string[] = [];
|
||||
const removeAdminData: string[] = [];
|
||||
const addOrUpdateSignerData: string[] = [];
|
||||
const removeSignerData: string[] = [];
|
||||
|
||||
// Remove all existing admins not included in the passed snapshot.
|
||||
const allAdmins = await this.getAllAdmins();
|
||||
const allToMakeAdmin = resolvedSnapshot
|
||||
.filter((item) => item.makeAdmin)
|
||||
.map((item) => item.signer);
|
||||
allAdmins.forEach((admin) => {
|
||||
if (!allToMakeAdmin.includes(admin)) {
|
||||
removeAdminData.push(
|
||||
this.contractWrapper.writeContract.interface.encodeFunctionData(
|
||||
"setAdmin",
|
||||
[admin, false],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove all existing signers not included in the passed snapshot.
|
||||
const allSigners = await this.getAllSigners();
|
||||
const allToMakeSigners = resolvedSnapshot
|
||||
.filter((item) => {
|
||||
return !item.makeAdmin;
|
||||
})
|
||||
.map((item) => item.signer);
|
||||
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",
|
||||
});
|
||||
|
||||
removeSignerData.push(data);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
for (const member of resolvedSnapshot) {
|
||||
// Add new admin
|
||||
if (member.makeAdmin) {
|
||||
addAdminData.push(
|
||||
this.contractWrapper.writeContract.interface.encodeFunctionData(
|
||||
"setAdmin",
|
||||
[member.signer, true],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Add new scoped
|
||||
const data = await this.buildSignerPermissionRequest(
|
||||
member.signer,
|
||||
member.permissions,
|
||||
);
|
||||
addOrUpdateSignerData.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
const data: string[] = [];
|
||||
removeAdminData.forEach((item) => {
|
||||
data.push(item);
|
||||
});
|
||||
removeSignerData.forEach((item) => {
|
||||
data.push(item);
|
||||
});
|
||||
addOrUpdateSignerData.forEach((item) => {
|
||||
data.push(item);
|
||||
});
|
||||
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "multicall",
|
||||
args: [data],
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1,190 +1,48 @@
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { FEATURE_ACCOUNT } from "../../constants/thirdweb-features";
|
||||
import { utils, BigNumber } from "ethers";
|
||||
import { Transaction } from "./transactions";
|
||||
|
||||
import type {
|
||||
IAccountCore,
|
||||
IAccountPermissions,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import {
|
||||
SignedSignerPermissionsPayload,
|
||||
SignerPermissionsOutput,
|
||||
FEATURE_ACCOUNT,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
} from "../../constants/thirdweb-features";
|
||||
|
||||
import type { IAccountCore } from "@thirdweb-dev/contracts-js";
|
||||
import {
|
||||
SignerWithPermissions,
|
||||
SignerPermissions,
|
||||
SignerPermissionsInput,
|
||||
SignerPermissionRequest,
|
||||
SignerPermissionsSchema,
|
||||
PermissionSnapshotInput,
|
||||
PermissionSnapshotSchema,
|
||||
PermissionSnapshotOutput,
|
||||
} from "../../types";
|
||||
import invariant from "tiny-invariant";
|
||||
import { buildTransactionFunction } from "../../common/transactions";
|
||||
import { resolveOrGenerateId } from "../../common/signature-minting";
|
||||
import { AddressOrEns } from "../../schema";
|
||||
import { resolveAddress } from "../../common";
|
||||
import { assertEnabled, detectContractFeature } from "../../common";
|
||||
import { AccountPermissions } from "./account-permissions";
|
||||
|
||||
export class Account<TContract extends IAccountCore>
|
||||
implements DetectableFeature
|
||||
{
|
||||
featureName = FEATURE_ACCOUNT.name;
|
||||
private contractWrapper: ContractWrapper<IAccountCore>;
|
||||
private accountPermissions: AccountPermissions | undefined;
|
||||
|
||||
constructor(contractWrapper: ContractWrapper<TContract>) {
|
||||
this.contractWrapper = contractWrapper;
|
||||
this.accountPermissions = this.detectAccountPermissions();
|
||||
}
|
||||
|
||||
private detectAccountPermissions(): AccountPermissions | undefined {
|
||||
if (
|
||||
detectContractFeature<IAccountCore>(
|
||||
this.contractWrapper,
|
||||
"AccountPermissions",
|
||||
)
|
||||
) {
|
||||
return new AccountPermissions(this.contractWrapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getAddress(): string {
|
||||
return this.contractWrapper.readContract.address;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* HELPER FUNCTIONS
|
||||
********************************/
|
||||
|
||||
private hasDuplicateSigners(snapshot: PermissionSnapshotOutput): boolean {
|
||||
const checkedSigner: Record<string, boolean> = {};
|
||||
|
||||
const signers = snapshot.map((item) => item.signer);
|
||||
|
||||
for (const signer of signers) {
|
||||
if (!checkedSigner[signer]) {
|
||||
checkedSigner[signer] = true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the access restrictions for a given role
|
||||
*
|
||||
* @param restrictions - The access restrictions for a given role
|
||||
* @returns formatted role restrictions
|
||||
*
|
||||
*/
|
||||
private parseSignerPermissionsStruct(
|
||||
permissions: IAccountPermissions.SignerPermissionsStruct,
|
||||
): SignerPermissions {
|
||||
return {
|
||||
startDate: new Date(
|
||||
parseInt(permissions.startTimestamp.toString()) * 1000,
|
||||
),
|
||||
expirationDate: new Date(
|
||||
parseInt(permissions.endTimestamp.toString()) * 1000,
|
||||
),
|
||||
nativeTokenLimitPerTransaction: BigNumber.from(
|
||||
permissions.nativeTokenLimitPerTransaction,
|
||||
),
|
||||
approvedCallTargets: permissions.approvedTargets,
|
||||
};
|
||||
}
|
||||
|
||||
private async sendSignerPermissionRequest(
|
||||
signerAddress: string,
|
||||
permissions: SignerPermissionsOutput,
|
||||
): Promise<Transaction> {
|
||||
const { payload, signature } = await this.generatePayload(
|
||||
signerAddress,
|
||||
permissions,
|
||||
);
|
||||
|
||||
const { success } =
|
||||
await this.contractWrapper.readContract.verifySignerPermissionRequest(
|
||||
payload,
|
||||
signature,
|
||||
);
|
||||
if (!success) {
|
||||
throw new Error(`Invalid signature.`);
|
||||
}
|
||||
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "setPermissionsForSigner",
|
||||
args: [payload, signature],
|
||||
});
|
||||
}
|
||||
|
||||
private async buildSignerPermissionRequest(
|
||||
signerAddress: string,
|
||||
permissions: SignerPermissionsOutput,
|
||||
): Promise<string> {
|
||||
const { payload, signature } = await this.generatePayload(
|
||||
signerAddress,
|
||||
permissions,
|
||||
);
|
||||
|
||||
const isValidSigner =
|
||||
await this.contractWrapper.readContract.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.
|
||||
*
|
||||
* @param signer - The address of the signer
|
||||
* @param roleAction - The address of the signer
|
||||
* @returns The generated payload and signature produced on signing that payload.
|
||||
*
|
||||
*/
|
||||
private async generatePayload(
|
||||
signerAddress: string,
|
||||
permissions: SignerPermissionsOutput,
|
||||
): Promise<SignedSignerPermissionsPayload> {
|
||||
// Get payload struct.
|
||||
const payload: IAccountPermissions.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),
|
||||
};
|
||||
|
||||
// Generate signature
|
||||
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 },
|
||||
payload,
|
||||
);
|
||||
|
||||
return { payload, signature };
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* READ FUNCTIONS
|
||||
********************************/
|
||||
@@ -199,13 +57,13 @@ export class Account<TContract extends IAccountCore>
|
||||
* @param signer - The address of a signer of the account.
|
||||
* @returns whether a signer is an admin on the account.
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async isAdmin(signerAddress: AddressOrEns): Promise<boolean> {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return await this.contractWrapper.readContract.isAdmin(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).isAdmin(signerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,13 +76,13 @@ export class Account<TContract extends IAccountCore>
|
||||
* @param signer - The address of a signer of the account.
|
||||
* @returns whether a signer has permissions to use the account.
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async isSigner(signerAddress: AddressOrEns): Promise<boolean> {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return await this.contractWrapper.readContract.isActiveSigner(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).isSigner(signerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,10 +95,13 @@ export class Account<TContract extends IAccountCore>
|
||||
*
|
||||
* @returns all admins of the account.
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async getAllAdmins(): Promise<string[]> {
|
||||
return await this.contractWrapper.readContract.getAllAdmins();
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).getAllAdmins();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,21 +114,13 @@ export class Account<TContract extends IAccountCore>
|
||||
*
|
||||
* @returns all (non-admin) signers with permissions to use the account.
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async getAllSigners(): Promise<SignerWithPermissions[]> {
|
||||
const activeSignersWithPerms: IAccountPermissions.SignerPermissionsStruct[] =
|
||||
await this.contractWrapper.readContract.getAllActiveSigners();
|
||||
|
||||
return await Promise.all(
|
||||
activeSignersWithPerms.map(async (signerWithPermissions) => {
|
||||
const signer = signerWithPermissions.signer;
|
||||
const permissions = this.parseSignerPermissionsStruct(
|
||||
signerWithPermissions,
|
||||
);
|
||||
return { signer, permissions };
|
||||
}),
|
||||
);
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).getAllSigners();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,27 +133,13 @@ export class Account<TContract extends IAccountCore>
|
||||
*
|
||||
* @returns all admins and non-admin signers with permissions to use the account.
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
public async getAllAdminsAndSigners(): Promise<SignerWithPermissions[]> {
|
||||
const allAdmins = await this.getAllAdmins();
|
||||
const transformedAdmins: SignerWithPermissions[] = allAdmins.map(
|
||||
(admin) => {
|
||||
return {
|
||||
isAdmin: true,
|
||||
signer: admin,
|
||||
permissions: {
|
||||
startDate: new Date(0),
|
||||
expirationDate: new Date(0),
|
||||
nativeTokenLimitPerTransaction: BigNumber.from(0),
|
||||
approvedCallTargets: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
);
|
||||
const allSigners = await this.getAllSigners();
|
||||
|
||||
return [...transformedAdmins, ...allSigners];
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).getAllAdminsAndSigners();
|
||||
}
|
||||
|
||||
/*********************************
|
||||
@@ -320,18 +159,14 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
grantAdminPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "setAdmin",
|
||||
args: [resolvedSignerAddress, true],
|
||||
});
|
||||
},
|
||||
);
|
||||
public async grantAdminPermissions(signerAddress: AddressOrEns) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).grantAdminPermissions(signerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke an address' admin access to the account.
|
||||
@@ -346,18 +181,14 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
revokeAdminPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "setAdmin",
|
||||
args: [resolvedSignerAddress, false],
|
||||
});
|
||||
},
|
||||
);
|
||||
public async revokeAdminPermissions(signerAddress: AddressOrEns) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).revokeAdminPermissions(signerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant a signer permissions to use the account.
|
||||
@@ -373,36 +204,17 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
grantPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
permissions: SignerPermissionsInput,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedPermissions = await SignerPermissionsSchema.parseAsync(
|
||||
permissions,
|
||||
);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot grant permissions to an existing admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (await this.isSigner(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer already has permissions. Cannot grant permissions to an existing signer. You can update permissions using `updatePermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
return await this.sendSignerPermissionRequest(
|
||||
resolvedSignerAddress,
|
||||
resolvedPermissions,
|
||||
);
|
||||
},
|
||||
);
|
||||
public async grantPermissions(
|
||||
signerAddress: AddressOrEns,
|
||||
permissions: SignerPermissionsInput,
|
||||
) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).grantPermissions(signerAddress, permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the permissions of a signer for using the account.
|
||||
@@ -418,36 +230,17 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
updatePermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
permissions: SignerPermissionsInput,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedPermissions = await SignerPermissionsSchema.parseAsync(
|
||||
permissions,
|
||||
);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot update permissions of an existing admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
return await this.sendSignerPermissionRequest(
|
||||
resolvedSignerAddress,
|
||||
resolvedPermissions,
|
||||
);
|
||||
},
|
||||
);
|
||||
public async updatePermissions(
|
||||
signerAddress: AddressOrEns,
|
||||
permissions: SignerPermissionsInput,
|
||||
) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).updatePermissions(signerAddress, permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke a scoped access address to the account
|
||||
@@ -462,32 +255,14 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
revokeAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot revoke permissions of an admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
return await this.sendSignerPermissionRequest(resolvedSignerAddress, {
|
||||
startDate: BigNumber.from(0),
|
||||
expirationDate: BigNumber.from(0),
|
||||
approvedCallTargets: [],
|
||||
nativeTokenLimitPerTransaction: "0",
|
||||
});
|
||||
},
|
||||
);
|
||||
public async revokeAccess(signerAddress: AddressOrEns) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).revokeAccess(signerAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve an address as a call target for a given signer on the account
|
||||
@@ -503,48 +278,17 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
approveTargetForSigner = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
target: AddressOrEns,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedTarget = await resolveAddress(target);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot approve targets for an admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
const permissions: IAccountPermissions.SignerPermissionsStruct =
|
||||
await this.contractWrapper.readContract.getPermissionsForSigner(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
|
||||
if (permissions.approvedTargets.includes(target)) {
|
||||
throw new Error("Target is already approved");
|
||||
}
|
||||
|
||||
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(),
|
||||
});
|
||||
},
|
||||
);
|
||||
public async approveTargetForSigner(
|
||||
signerAddress: AddressOrEns,
|
||||
target: AddressOrEns,
|
||||
) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).approveTargetForSigner(signerAddress, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disapprove an address as a call target for a given signer on the account
|
||||
@@ -560,51 +304,17 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
disapproveTargetForSigner = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
signerAddress: AddressOrEns,
|
||||
target: AddressOrEns,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
const resolvedTarget = await resolveAddress(target);
|
||||
|
||||
if (await this.isAdmin(resolvedSignerAddress)) {
|
||||
throw new Error(
|
||||
"Signer is already an admin. Cannot approve targets for an admin.",
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await this.isSigner(resolvedSignerAddress))) {
|
||||
throw new Error(
|
||||
"Signer does not already have permissions. You can grant permissions using `grantPermissions`.",
|
||||
);
|
||||
}
|
||||
|
||||
const permissions: IAccountPermissions.SignerPermissionsStruct =
|
||||
await this.contractWrapper.readContract.getPermissionsForSigner(
|
||||
resolvedSignerAddress,
|
||||
);
|
||||
|
||||
if (!permissions.approvedTargets.includes(resolvedTarget)) {
|
||||
throw new Error("Target is currently not approved");
|
||||
}
|
||||
|
||||
const newTargets = permissions.approvedTargets.filter(
|
||||
(approvedTarget) =>
|
||||
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(),
|
||||
});
|
||||
},
|
||||
);
|
||||
public async disapproveTargetForSigner(
|
||||
signerAddress: AddressOrEns,
|
||||
target: AddressOrEns,
|
||||
) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).disapproveTargetForSigner(signerAddress, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the account's entire snapshot of permissions.
|
||||
@@ -619,111 +329,14 @@ export class Account<TContract extends IAccountCore>
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature Account
|
||||
* @twfeature AccountPermissions
|
||||
*/
|
||||
resetAllPermissions = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
permissionSnapshot: PermissionSnapshotInput,
|
||||
): Promise<Transaction> => {
|
||||
const resolvedSnapshot = await PermissionSnapshotSchema.parseAsync(
|
||||
permissionSnapshot,
|
||||
);
|
||||
|
||||
/**
|
||||
* All cases
|
||||
*
|
||||
* - Add new admin :check:
|
||||
* - Remove current admin :check:
|
||||
* - Add new scoped :check:
|
||||
* - Remove current scoped :check:
|
||||
* - Update current scoped :check:
|
||||
* - Current admin -> new scoped :check:
|
||||
* - Current scoped -> new admin :check:
|
||||
**/
|
||||
|
||||
// No duplicate signers in input!
|
||||
if (this.hasDuplicateSigners(resolvedSnapshot)) {
|
||||
throw new Error("Duplicate signers found in input.");
|
||||
}
|
||||
|
||||
const addAdminData: string[] = [];
|
||||
const removeAdminData: string[] = [];
|
||||
const addOrUpdateSignerData: string[] = [];
|
||||
const removeSignerData: string[] = [];
|
||||
|
||||
// Remove all existing admins not included in the passed snapshot.
|
||||
const allAdmins = await this.getAllAdmins();
|
||||
const allToMakeAdmin = resolvedSnapshot
|
||||
.filter((item) => item.makeAdmin)
|
||||
.map((item) => item.signer);
|
||||
allAdmins.forEach((admin) => {
|
||||
if (!allToMakeAdmin.includes(admin)) {
|
||||
removeAdminData.push(
|
||||
this.contractWrapper.writeContract.interface.encodeFunctionData(
|
||||
"setAdmin",
|
||||
[admin, false],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove all existing signers not included in the passed snapshot.
|
||||
const allSigners = await this.getAllSigners();
|
||||
const allToMakeSigners = resolvedSnapshot
|
||||
.filter((item) => {
|
||||
return !item.makeAdmin;
|
||||
})
|
||||
.map((item) => item.signer);
|
||||
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",
|
||||
});
|
||||
|
||||
removeSignerData.push(data);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
for (const member of resolvedSnapshot) {
|
||||
// Add new admin
|
||||
if (member.makeAdmin) {
|
||||
addAdminData.push(
|
||||
this.contractWrapper.writeContract.interface.encodeFunctionData(
|
||||
"setAdmin",
|
||||
[member.signer, true],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Add new scoped
|
||||
const data = await this.buildSignerPermissionRequest(
|
||||
member.signer,
|
||||
member.permissions,
|
||||
);
|
||||
addOrUpdateSignerData.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
const data: string[] = [];
|
||||
removeAdminData.forEach((item) => {
|
||||
data.push(item);
|
||||
});
|
||||
removeSignerData.forEach((item) => {
|
||||
data.push(item);
|
||||
});
|
||||
addOrUpdateSignerData.forEach((item) => {
|
||||
data.push(item);
|
||||
});
|
||||
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "multicall",
|
||||
args: [data],
|
||||
});
|
||||
},
|
||||
);
|
||||
public async resetAllPermissions(
|
||||
permissionSnapshot: PermissionSnapshotInput,
|
||||
) {
|
||||
return assertEnabled(
|
||||
this.accountPermissions,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
).resetAllPermissions(permissionSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/unity-js-bridge
|
||||
|
||||
## 0.2.68
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74), [`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/wallets@1.1.14
|
||||
- @thirdweb-dev/sdk@3.10.50
|
||||
- @thirdweb-dev/auth@3.2.31
|
||||
|
||||
## 0.2.67
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/unity-js-bridge",
|
||||
"version": "0.2.67",
|
||||
"version": "0.2.68",
|
||||
"main": "dist/thirdweb-unity-bridge.js",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @thirdweb-dev/wallets
|
||||
|
||||
## 1.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1484](https://github.com/thirdweb-dev/js/pull/1484) [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Correct gas estimation for polygon/mumbai
|
||||
|
||||
- Updated dependencies [[`a5ba9e4f`](https://github.com/thirdweb-dev/js/commit/a5ba9e4fbfee228e5b9ac27cd0157187e3a50117), [`39e2af6f`](https://github.com/thirdweb-dev/js/commit/39e2af6f2f4d933dca1b3de4a37de76375bafd74)]:
|
||||
- @thirdweb-dev/sdk@3.10.50
|
||||
|
||||
## 1.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/wallets",
|
||||
"version": "1.1.13",
|
||||
"version": "1.1.14",
|
||||
"main": "dist/thirdweb-dev-wallets.cjs.js",
|
||||
"module": "dist/thirdweb-dev-wallets.esm.js",
|
||||
"types": "dist/thirdweb-dev-wallets.cjs.d.ts",
|
||||
|
||||
@@ -18,7 +18,10 @@ import {
|
||||
CeloAlfajoresTestnet,
|
||||
CeloBaklavaTestnet,
|
||||
Celo,
|
||||
Mumbai,
|
||||
Polygon,
|
||||
} from "@thirdweb-dev/chains";
|
||||
import { getPolygonGasPriorityFee } from "@thirdweb-dev/sdk";
|
||||
|
||||
export interface BaseApiParams {
|
||||
provider: providers.Provider;
|
||||
@@ -291,6 +294,9 @@ export abstract class BaseAccountAPI {
|
||||
let { maxFeePerGas, maxPriorityFeePerGas } = info;
|
||||
if (!maxFeePerGas || !maxPriorityFeePerGas) {
|
||||
const feeData = await this.provider.getFeeData();
|
||||
if (!maxPriorityFeePerGas) {
|
||||
maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? undefined;
|
||||
}
|
||||
if (!maxFeePerGas) {
|
||||
maxFeePerGas = feeData.maxFeePerGas ?? undefined;
|
||||
const network = await this.provider.getNetwork();
|
||||
@@ -303,9 +309,22 @@ export abstract class BaseAccountAPI {
|
||||
) {
|
||||
maxPriorityFeePerGas = maxFeePerGas;
|
||||
}
|
||||
}
|
||||
if (!maxPriorityFeePerGas) {
|
||||
maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? undefined;
|
||||
|
||||
if (
|
||||
maxPriorityFeePerGas &&
|
||||
(chainId === Mumbai.chainId || chainId === Polygon.chainId)
|
||||
) {
|
||||
// for polygon/mumbai, override fee data from gas station
|
||||
const block = await this.provider.getBlock("latest");
|
||||
const baseBlockFee =
|
||||
block && block.baseFeePerGas
|
||||
? block.baseFeePerGas
|
||||
: utils.parseUnits("1", "gwei");
|
||||
maxPriorityFeePerGas = await getPolygonGasPriorityFee(chainId);
|
||||
// See: https://eips.ethereum.org/EIPS/eip-1559 for formula
|
||||
const baseMaxFeePerGas = baseBlockFee.mul(2);
|
||||
maxFeePerGas = baseMaxFeePerGas.add(maxPriorityFeePerGas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user