[TS SDK] Feature: Accept a string for signature mint UID (#4270)
## Problem solved
Auto-encodes strings passed to `generateSignatureMint` across all token types. This change could cause confusion since the response uid from the contract will still be in hex form.
<!-- start pr-codex -->
---
## PR-Codex overview
This PR allows accepting string UIDs for signature minting in ERC721 and ERC20 contracts.
### Detailed summary
- Updated functions to accept and encode string UIDs for minting signatures
- Added tests for generating mint signatures with custom string UIDs
- Updated dependencies and peer dependencies in package.json
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"thirdweb": patch
|
||||
---
|
||||
|
||||
Allow accepting a string for signature mint UIDs
|
||||
@@ -23,7 +23,10 @@
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"files": ["dist/*", "src/*"],
|
||||
"files": [
|
||||
"dist/*",
|
||||
"src/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-lambda": "3.577.0",
|
||||
"@aws-sdk/credential-providers": "3.577.0",
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { ThirdwebContract } from "../../../contract/contract.js";
|
||||
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
||||
import { toBigInt } from "../../../utils/bigint.js";
|
||||
import { dateToSeconds, tenYearsFromNow } from "../../../utils/date.js";
|
||||
import type { Hex } from "../../../utils/encoding/hex.js";
|
||||
import { type Hex, isHex, stringToHex } from "../../../utils/encoding/hex.js";
|
||||
import type { NFTInput } from "../../../utils/nft/parseNft.js";
|
||||
import { randomBytesHex } from "../../../utils/random.js";
|
||||
import type { Account } from "../../../wallets/interfaces/wallet.js";
|
||||
@@ -135,7 +135,14 @@ export async function generateMintSignature(
|
||||
return "";
|
||||
})(),
|
||||
// uid computation
|
||||
mintRequest.uid || (await randomBytesHex()),
|
||||
((): Hex => {
|
||||
if (mintRequest.uid) {
|
||||
return isHex(mintRequest.uid)
|
||||
? mintRequest.uid
|
||||
: stringToHex(mintRequest.uid, { size: 32 });
|
||||
}
|
||||
return randomBytesHex();
|
||||
})(),
|
||||
]);
|
||||
|
||||
const startTime = mintRequest.validityStartTimestamp || new Date(0);
|
||||
@@ -190,7 +197,7 @@ type GeneratePayloadInput = {
|
||||
currency?: Address;
|
||||
validityStartTimestamp?: Date;
|
||||
validityEndTimestamp?: Date;
|
||||
uid?: Hex;
|
||||
uid?: string;
|
||||
} & (
|
||||
| {
|
||||
metadata: NFTInput | string;
|
||||
|
||||
@@ -194,4 +194,38 @@ describe.runIf(process.env.TW_SECRET_KEY)("generateMintSignature1155", () => {
|
||||
expect(payload.uid).toBe(uid);
|
||||
expect(signature.length).toBe(132);
|
||||
});
|
||||
|
||||
it("should generate a mint signature with custom values", async () => {
|
||||
const { payload, signature } = await generateMintSignature({
|
||||
mintRequest: {
|
||||
to: TEST_ACCOUNT_B.address,
|
||||
quantity: 10n,
|
||||
royaltyRecipient: TEST_ACCOUNT_B.address,
|
||||
royaltyBps: 500,
|
||||
primarySaleRecipient: TEST_ACCOUNT_A.address,
|
||||
tokenId: 0n,
|
||||
pricePerToken: "0.2",
|
||||
currency: erc20TokenContract.address,
|
||||
validityStartTimestamp: new Date(1635724800),
|
||||
validityEndTimestamp: new Date(1867260800),
|
||||
uid: "abcdef1234567890",
|
||||
},
|
||||
account: TEST_ACCOUNT_A,
|
||||
contract: erc1155Contract,
|
||||
});
|
||||
|
||||
expect(payload.to).toBe(TEST_ACCOUNT_B.address);
|
||||
expect(payload.tokenId).toBe(0n);
|
||||
expect(payload.royaltyRecipient).toBe(TEST_ACCOUNT_B.address);
|
||||
expect(payload.royaltyBps).toBe(500n);
|
||||
expect(payload.primarySaleRecipient).toBe(TEST_ACCOUNT_A.address);
|
||||
expect(payload.uri).toBe("");
|
||||
expect(payload.pricePerToken).toBe(200000000000000000n);
|
||||
expect(payload.quantity).toBe(10n);
|
||||
expect(payload.currency).toBe(erc20TokenContract.address);
|
||||
expect(payload.validityStartTimestamp).toBe(1635724n);
|
||||
expect(payload.validityEndTimestamp).toBe(1867260n);
|
||||
expect(payload.uid).toBe(toHex("abcdef1234567890", { size: 32 }));
|
||||
expect(signature.length).toBe(132);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
import type { ThirdwebContract } from "../../../contract/contract.js";
|
||||
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
||||
import { dateToSeconds, tenYearsFromNow } from "../../../utils/date.js";
|
||||
import type { Hex } from "../../../utils/encoding/hex.js";
|
||||
import { type Hex, isHex, stringToHex } from "../../../utils/encoding/hex.js";
|
||||
import { randomBytesHex } from "../../../utils/random.js";
|
||||
import type { Account } from "../../../wallets/interfaces/wallet.js";
|
||||
import { name } from "../../common/read/name.js";
|
||||
@@ -139,8 +139,14 @@ export async function generateMintSignature(
|
||||
erc20Address: contract.address,
|
||||
});
|
||||
})(),
|
||||
// uid computation
|
||||
mintRequest.uid || (await randomBytesHex()),
|
||||
((): Hex => {
|
||||
if (mintRequest.uid) {
|
||||
return isHex(mintRequest.uid)
|
||||
? mintRequest.uid
|
||||
: stringToHex(mintRequest.uid, { size: 32 });
|
||||
}
|
||||
return randomBytesHex();
|
||||
})(),
|
||||
// ERC20Permit (EIP-712) spec differs from signature mint 721, 1155.
|
||||
// it uses the token name in the domain separator
|
||||
name({
|
||||
@@ -190,7 +196,7 @@ type GeneratePayloadInput = {
|
||||
currency?: Address;
|
||||
validityStartTimestamp?: Date;
|
||||
validityEndTimestamp?: Date;
|
||||
uid?: Hex;
|
||||
uid?: string;
|
||||
} & ({ quantity: string } | { quantityWei: bigint });
|
||||
|
||||
export const MintRequest20 = [
|
||||
|
||||
@@ -137,4 +137,35 @@ describe.runIf(process.env.TW_SECRET_KEY)("generateMintSignature20", () => {
|
||||
);
|
||||
expect(signature.length).toBe(132);
|
||||
});
|
||||
|
||||
it("should automatically encode a provided string uid", async () => {
|
||||
const { payload, signature } = await generateMintSignature({
|
||||
mintRequest: {
|
||||
to: TEST_ACCOUNT_B.address,
|
||||
quantity: "0.005",
|
||||
primarySaleRecipient: TEST_ACCOUNT_A.address,
|
||||
price: "0.2",
|
||||
currency: erc20TokenContract.address,
|
||||
validityStartTimestamp: new Date(1635724800),
|
||||
validityEndTimestamp: new Date(1867260800),
|
||||
uid: "abcdef1234567890",
|
||||
},
|
||||
account: TEST_ACCOUNT_A,
|
||||
contract: erc20Contract,
|
||||
});
|
||||
|
||||
expect(payload.to).toBe("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
|
||||
expect(payload.primarySaleRecipient).toBe(
|
||||
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||
);
|
||||
expect(payload.quantity).toBe(5000000000000000n);
|
||||
expect(payload.price).toBe(200000000000000000n);
|
||||
expect(payload.currency).toBe(erc20TokenContract.address);
|
||||
expect(payload.validityStartTimestamp).toBe(1635724n);
|
||||
expect(payload.validityEndTimestamp).toBe(1867260n);
|
||||
expect(payload.uid).toBe(
|
||||
"0x6162636465663132333435363738393000000000000000000000000000000000",
|
||||
);
|
||||
expect(signature.length).toBe(132);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AbiParameterToPrimitiveType, Address } from "abitype";
|
||||
import type { Hex } from "viem";
|
||||
import { type Hex, isHex, stringToHex } from "viem";
|
||||
import {
|
||||
NATIVE_TOKEN_ADDRESS,
|
||||
isNativeTokenAddress,
|
||||
@@ -131,7 +131,14 @@ export async function generateMintSignature(
|
||||
return "";
|
||||
})(),
|
||||
// uid computation
|
||||
mintRequest.uid || (await randomBytesHex()),
|
||||
((): Hex => {
|
||||
if (mintRequest.uid) {
|
||||
return isHex(mintRequest.uid)
|
||||
? mintRequest.uid
|
||||
: stringToHex(mintRequest.uid, { size: 32 });
|
||||
}
|
||||
return randomBytesHex();
|
||||
})(),
|
||||
]);
|
||||
|
||||
const startTime = mintRequest.validityStartTimestamp || new Date(0);
|
||||
@@ -212,7 +219,7 @@ type GeneratePayloadInput = {
|
||||
currency?: Address;
|
||||
validityStartTimestamp?: Date;
|
||||
validityEndTimestamp?: Date;
|
||||
uid?: Hex;
|
||||
uid?: string;
|
||||
};
|
||||
|
||||
const MintRequest721 = [
|
||||
|
||||
@@ -156,6 +156,43 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
||||
expect(signature.length).toBe(132);
|
||||
});
|
||||
|
||||
it("should automatically encode a provided string uid", async () => {
|
||||
const { payload, signature } = await generateMintSignature({
|
||||
mintRequest: {
|
||||
to: TEST_ACCOUNT_B.address,
|
||||
royaltyRecipient: TEST_ACCOUNT_B.address,
|
||||
royaltyBps: 500,
|
||||
primarySaleRecipient: TEST_ACCOUNT_A.address,
|
||||
metadata: "https://example.com/token",
|
||||
price: "0.2",
|
||||
currency: erc20TokenContract.address,
|
||||
validityStartTimestamp: new Date(1635724800),
|
||||
validityEndTimestamp: new Date(1867260800),
|
||||
uid: "abcdef1234567890",
|
||||
},
|
||||
account: TEST_ACCOUNT_A,
|
||||
contract: erc721Contract,
|
||||
});
|
||||
|
||||
expect(payload.to).toBe("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
|
||||
expect(payload.royaltyRecipient).toBe(
|
||||
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
|
||||
);
|
||||
expect(payload.royaltyBps).toBe(500n);
|
||||
expect(payload.primarySaleRecipient).toBe(
|
||||
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||
);
|
||||
expect(payload.uri).toBe("https://example.com/token");
|
||||
expect(payload.price).toBe(200000000000000000n);
|
||||
expect(payload.currency).toBe(erc20TokenContract.address);
|
||||
expect(payload.validityStartTimestamp).toBe(1635724n);
|
||||
expect(payload.validityEndTimestamp).toBe(1867260n);
|
||||
expect(payload.uid).toBe(
|
||||
"0x6162636465663132333435363738393000000000000000000000000000000000",
|
||||
);
|
||||
expect(signature.length).toBe(132);
|
||||
});
|
||||
|
||||
it("should default sale recipient to the contract's primarySaleRecipient when empty", async () => {
|
||||
const { payload, signature } = await generateMintSignature({
|
||||
mintRequest: {
|
||||
|
||||
Reference in New Issue
Block a user