Skip to content

Commit

Permalink
update docs and api
Browse files Browse the repository at this point in the history
  • Loading branch information
iainnash committed Oct 26, 2023
1 parent 057c9ab commit 1d9df4d
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 36 deletions.
55 changes: 55 additions & 0 deletions packages/premint-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,61 @@ async function makePremint(walletClient: WalletClient) {

```

### Updating a premint:

```js
import {PremintAPI} from '@zoralabs/premint-sdk';
import type {Address, WalletClient} from 'viem';

async function updatePremint(walletClient: WalletClient) {
// Create premint API object passing in the current wallet chain (only zora and zora testnet are supported currently).
const premintAPI = new PremintAPI(walletClient.chain);

// Create premint
const premint = await premintAPI.updatePremint({
// Extra step to check the signature on-chain before attempting to sign
collection: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
uid: 23,
// WalletClient doing the signature
walletClient,
// Token information, falls back to defaults set in DefaultMintArguments.
token: {
tokenURI:
"ipfs://bafkreice23maski3x52tsfqgxstx3kbiifnt5jotg3a5ynvve53c4soi2u",
},
});

console.log(`updated ZORA premint, link: ${premint.url}`)
return premint;
}

```

### Deleting a premint:

```js
import {PremintAPI} from '@zoralabs/premint-sdk';
import type {Address, WalletClient} from 'viem';

async function deletePremint(walletClient: WalletClient) {
// Create premint API object passing in the current wallet chain (only zora and zora testnet are supported currently).
const premintAPI = new PremintAPI(walletClient.chain);

// Create premint
const premint = await premintAPI.deletePremint({
// Extra step to check the signature on-chain before attempting to sign
collection: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
uid: 23,
// WalletClient doing the signature
walletClient,
});

console.log(`updated ZORA premint, link: ${premint.url}`)
return premint;
}

```

### Executing a premint:

```js
Expand Down
2 changes: 1 addition & 1 deletion packages/premint-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"build": "tsup",
"prepack": "yarn build",
"test": "vitest src",
"generate-types": "npx openapi-typescript https://api.zora.co/premint/openapi.json -o src/generated/premint-api-types.ts",
"generate-types": "npx openapi-typescript https://api.zora.co/premint/openapi.json -o src/generated/premint-api-types.ts && npx openapi-typescript https://api.zora.co/discover/openapi.json -o src/generated/discover-api-types.ts",
"anvil": "source .env.anvil && anvil --fork-url $FORK_RPC_URL --fork-block-number $FORK_BLOCK_NUMBER --chain-id 31337"
},
"dependencies": {
Expand Down
15 changes: 8 additions & 7 deletions packages/premint-sdk/src/http-api-base.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export class BadResponse<T = any> extends Error {
export class BadResponseError<T = any> extends Error {
status: number;
json: T;
constructor(message: string, status: number, json: any) {
super(message);
this.name = "BadResponse";
this.name = "BadResponseError";
this.status = status;
this.json = json;
}
Expand All @@ -30,7 +30,7 @@ export const get = async <T>(url: string) => {
try {
json = await response.json();
} catch (e: any) {}
throw new BadResponse(
throw new BadResponseError(
`Invalid response, status ${response.status}`,
response.status,
json
Expand Down Expand Up @@ -62,7 +62,7 @@ export const post = async <T>(url: string, data: any) => {
try {
json = await response.json();
} catch (e: any) {}
throw new BadResponse(
throw new BadResponseError(
`Bad response: ${response.status}`,
response.status,
json
Expand All @@ -74,14 +74,15 @@ export const post = async <T>(url: string, data: any) => {
export const retries = async <T>(
tryFn: () => T,
maxTries: number = 3,
atTry: number = 1
atTry: number = 1,
linearBackoffMS: number = 200
): Promise<T> => {
try {
return await tryFn();
} catch (err: any) {
if (err instanceof BadResponse) {
if (err instanceof BadResponseError) {
if (atTry <= maxTries) {
await wait(500);
await wait(atTry * linearBackoffMS);
return await retries(tryFn, maxTries, atTry++);
}
}
Expand Down
12 changes: 8 additions & 4 deletions packages/premint-sdk/src/premint-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@ const postSignature = async (
const getNextUID = async (
path: PremintNextUIDGetPathParameters
): Promise<PremintNextUIDGetResponse> =>
get<PremintNextUIDGetResponse>(
`${ZORA_API_BASE}signature/${path.chain_name}/${path.collection_address}/next_uid`
retries(() =>
get<PremintNextUIDGetResponse>(
`${ZORA_API_BASE}signature/${path.chain_name}/${path.collection_address}/next_uid`
)
);

const getSignature = async (
path: PremintSignatureGetPathParameters
): Promise<PremintSignatureGetResponse> =>
get<PremintSignatureGetResponse>(
`signature/${path.chain_name}/${path.collection_address}/${path.uid}`
retries(() =>
get<PremintSignatureGetResponse>(
`signature/${path.chain_name}/${path.collection_address}/${path.uid}`
)
);

export const PremintAPIClient = {
Expand Down
35 changes: 19 additions & 16 deletions packages/premint-sdk/src/premint-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { foundry } from "viem/chains";
import { describe, it, beforeEach, expect, vi } from "vitest";
import { parseEther } from "viem";
import { BackendChainNames, PremintAPI } from "./premint-client";
import { BackendChainNames, PremintClient } from "./premint-client";

const chain = foundry;

Expand Down Expand Up @@ -48,16 +48,19 @@ describe("ZoraCreator1155Premint", () => {
});
}, 20 * 1000);

// skip for now - we need to make this work on zora testnet chain too
it(
"can sign on the forked premint contract",
async () => {
const premintApi = new PremintAPI(chain);
const premintClient = new PremintClient(chain);

premintApi.get = vi.fn().mockResolvedValue({ next_uid: 3 });
premintApi.post = vi.fn().mockResolvedValue({ ok: true });
premintClient.premintAPIClient.getNextUID = vi
.fn()
.mockResolvedValue({ next_uid: 3 });
premintClient.premintAPIClient.postSignature = vi
.fn()
.mockResolvedValue({ ok: true });

const premint = await premintApi.createPremint({
const premint = await premintClient.createPremint({
walletClient,
publicClient,
account: deployerAccount,
Expand All @@ -74,8 +77,7 @@ describe("ZoraCreator1155Premint", () => {
},
});

expect(premintApi.post).toHaveBeenCalledWith(
"https://api.zora.co/premint/signature",
expect(premintClient.premintAPIClient.postSignature).toHaveBeenCalledWith(
{
chain_name: BackendChainNames.ZORA_GOERLI,
collection: {
Expand Down Expand Up @@ -111,7 +113,7 @@ describe("ZoraCreator1155Premint", () => {
);

it("can validate premint on network", async () => {
const premint = new PremintAPI(chain);
const premintClient = new PremintClient(chain);

const premintData = {
collection: {
Expand Down Expand Up @@ -146,19 +148,20 @@ describe("ZoraCreator1155Premint", () => {
chain: foundry,
transport: http(),
});
const signatureValid = await premint.isValidSignature({
const signatureValid = await premintClient.isValidSignature({
// @ts-ignore: Fix enum type
data: premintData,
publicClient,
});
expect(signatureValid.isValid).toBe(true);
});

it(
"can execute premint on network",
async () => {
const premintApi = new PremintAPI(chain);
const premintClient = new PremintClient(chain);

premintApi.get = vi.fn().mockResolvedValue({
premintClient.premintAPIClient.getSignature = vi.fn().mockResolvedValue({
chain_name: "ZORA-TESTNET",
collection: {
contractAdmin: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
Expand Down Expand Up @@ -187,10 +190,10 @@ describe("ZoraCreator1155Premint", () => {
signature:
"0x588d19641de9ba1dade4d2bb5387c8dc96f4a990fef69787534b60caead759e6334975a6be10a796da948cd7d1d4f5580b3f84d49d9fa4e0b41c97759507975a1c",
});
premintApi.post = vi.fn();
premintClient.premintAPIClient.postSignature = vi.fn();

const premint = await premintApi.executePremintWithWallet({
data: await premintApi.getPremintData({
const premint = await premintClient.executePremintWithWallet({
data: await premintClient.getPremintData({
address: "0xf8dA7f53c283d898818af7FB9d98103F559bDac2",
uid: 3,
}),
Expand All @@ -203,7 +206,7 @@ describe("ZoraCreator1155Premint", () => {
},
});

expect(premint.log).toEqual({
expect(premint.premintedLog).toEqual({
contractAddress: "0xf8dA7f53c283d898818af7FB9d98103F559bDac2",
contractConfig: {
contractAdmin: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
Expand Down
29 changes: 21 additions & 8 deletions packages/premint-sdk/src/premint-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,13 @@ export const DefaultMintArguments = {
royaltyBPS: 1000, // 10%,
};

function getPremintedLogFromReceipt(
/**
* Gets the preminted log from receipt
*
* @param receipt Preminted log from receipt
* @returns Premint event arguments
*/
export function getPremintedLogFromReceipt(
receipt: TransactionReceipt
): PremintedLogType | undefined {
for (const data of receipt.logs) {
Expand All @@ -125,6 +131,7 @@ function getPremintedLogFromReceipt(

/**
* Convert server to on-chain types for a premint
*
* @param premint Premint object from the server to convert to one that's compatible with viem
* @returns Viem type-compatible premint object
*/
Expand Down Expand Up @@ -153,6 +160,7 @@ export const convertCollection = (

/**
* Convert on-chain types for a premint to a server safe type
*
* @param premint Premint object from viem to convert to a JSON compatible type.
* @returns JSON compatible premint
*/
Expand All @@ -175,13 +183,16 @@ export const encodePremintForAPI = ({
* Preminter API to access ZORA Premint functionality.
* Currently only supports V1 premints.
*/
export class PremintAPI {
export class PremintClient {
network: NetworkConfig;
chain: Chain;
premintAPIClient: typeof PremintAPIClient;

constructor(chain: Chain, premintAPIClient: typeof PremintAPIClient) {
constructor(chain: Chain, premintAPIClient?: typeof PremintAPIClient) {
this.chain = chain;
if (!premintAPIClient) {
premintAPIClient = PremintAPIClient;
}
this.premintAPIClient = premintAPIClient;
const networkConfig = networkConfigByChain[chain.id];
if (!networkConfig) {
Expand Down Expand Up @@ -255,7 +266,7 @@ export class PremintAPI {
account?: Account | Address;
collection: Address;
}): Promise<SignedPremintResponse> {
const signatureResponse = await getSignature({
const signatureResponse = await this.premintAPIClient.getSignature({
chain_name: this.network.zoraBackendChainName,
collection_address: collection.toLowerCase(),
uid: uid,
Expand Down Expand Up @@ -315,7 +326,7 @@ export class PremintAPI {
account?: Account | Address;
collection: Address;
}) {
const signatureResponse = await getSignature({
const signatureResponse = await this.premintAPIClient.getSignature({
chain_name: this.network.zoraBackendChainName,
collection_address: collection.toLowerCase(),
uid: uid,
Expand Down Expand Up @@ -343,6 +354,7 @@ export class PremintAPI {
}

/**
* Internal function to sign and submit a premint request.
*
* @param premintArguments Arguments to premint
* @returns
Expand Down Expand Up @@ -401,7 +413,7 @@ export class PremintAPI {
signature: signature,
};

const premint = await postSignature(apiData);
const premint = await this.premintAPIClient.postSignature(apiData);

return {
urls: this.makeUrls({ address: verifyingContract, uid }),
Expand Down Expand Up @@ -464,7 +476,7 @@ export class PremintAPI {

let uid = executionSettings?.uid;
if (!uid) {
const uidResponse = await getNextUID({
const uidResponse = await this.premintAPIClient.getNextUID({
chain_name: this.network.zoraBackendChainName,
collection_address: newContractAddress.toLowerCase(),
});
Expand All @@ -489,6 +501,7 @@ export class PremintAPI {
verifyingContract: newContractAddress,
premintConfig,
checkSignature,
account,
publicClient,
walletClient,
collection,
Expand All @@ -509,7 +522,7 @@ export class PremintAPI {
address: string;
uid: number;
}): Promise<PremintSignatureGetResponse> {
return await getSignature({
return await this.premintAPIClient.getSignature({
chain_name: this.network.zoraBackendChainName,
collection_address: address,
uid,
Expand Down

0 comments on commit 1d9df4d

Please sign in to comment.