Skip to content

Commit

Permalink
PremintClient updates: PremintApiClient is now a class, createPremint…
Browse files Browse the repository at this point in the history
…Client now follows pattern of createMintClient. executePremint renamed to makeMintParemeters (#390)

* premint client now follows standard mint client functinoality

* added changeset

* updated readme with better examples.  renamed premint mint function

* lint fix
  • Loading branch information
oveddan authored Nov 28, 2023
1 parent 69585fb commit a75632a
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 148 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-turtles-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zoralabs/protocol-sdk": patch
---

premintClient can have http methods overridable via DI, and now takes publicClient and http overrides in `createPremintClient` function. it no longer takes `publicClient` as an argument in functions, and rather uses them from the constructor. `executePremint` has been renamed ot `makeMintParameters`
145 changes: 81 additions & 64 deletions packages/protocol-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,53 +214,71 @@ export async function createContract({
}
```

### Creating a premint:
### Creating a token for free (gasless creation):

```ts
import { PremintAPI } from "@zoralabs/protocol-sdk";
import type { Address, WalletClient } from "viem";
import {createPremintClient} from "@zoralabs/protocol-sdk";
import type {Address, PublicClient, WalletClient} from "viem";

async function makePremint(walletClient: WalletClient) {
// Create premint
const premint = await createPremintAPI(walletClient.chain).createPremint({
// Extra step to check the signature on-chain before attempting to sign
async function createForFree({
walletClient,
creatorAccount,
}: {
// wallet client that will submit the transaction
walletClient: WalletClient;
// address of the token contract
creatorAccount: Address;
}) {
const premintClient = createPremintClient({ chain: walletClient.chain! });

// create and sign a free token creation.
const createdPremint = await premintClient.createPremint({
walletClient,
account: creatorAccount,
// if true, will validate that the creator is authorized to create premints on the contract.
checkSignature: true,
// Collection information that this premint NFT will exist in once minted.
// collection info of collection to create
collection: {
contractAdmin: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
contractAdmin: creatorAccount,
contractName: "Testing Contract",
contractURI:
"ipfs://bafkreiainxen4b4wz4ubylvbhons6rembxdet4a262nf2lziclqvv7au3e",
},
// WalletClient doing the signature
walletClient,
// Token information, falls back to defaults set in DefaultMintArguments.
// token info of token to create
token: {
tokenURI:
"ipfs://bafkreice23maski3x52tsfqgxstx3kbiifnt5jotg3a5ynvve53c4soi2u",
},
});

console.log(`created ZORA premint, link: ${premint.url}`);
return premint;
}
const premintUid = createdPremint.uid;
const premintCollectionAddress = createdPremint.verifyingContract;

return {
// unique id of created premint, which can be used later to
// update or delete the premint
uid: premintUid,
tokenContract: premintCollectionAddress,
}
}
```

### Updating a premint:
### Updating a token that was created for free (before it was brought onchain):

Before a token that was created for free is brought onchain, it can be updated by the original creator of that token, by having that creator sign a message indicating the update. This is useful for updating the tokenURI, other metadata, or token sale configuration (price, duration, limits, etc.):

```ts
import { PremintAPI } from "@zoralabs/premint-sdk";
import type { Address, WalletClient } from "viem";
import {createPremintClient} from "@zoralabs/protocol-sdk";
import type {Address, PublicClient, WalletClient} from "viem";

async function updatePremint(walletClient: WalletClient) {
async function updateCreatedForFreeToken(walletClient: WalletClient, premintUid: number) {
// Create premint API object passing in the current wallet chain (only zora and zora testnet are supported currently).
const premintAPI = createPremintAPI(walletClient.chain);
const premintClient = createPremintClient({ chain: walletClient.chain! });

// Create premint
const premint = await premintAPI.updatePremint({
// Extra step to check the signature on-chain before attempting to sign
// sign a message to update the created for free token, and store the update
await premintClient.updatePremint({
collection: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
uid: 23,
uid: premintUid,
// WalletClient doing the signature
walletClient,
// Token information, falls back to defaults set in DefaultMintArguments.
Expand All @@ -269,73 +287,72 @@ async function updatePremint(walletClient: WalletClient) {
"ipfs://bafkreice23maski3x52tsfqgxstx3kbiifnt5jotg3a5ynvve53c4soi2u",
},
});

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

### Deleting a premint:
### Deleting a token that was created for free (before it was brought onchain):

Before a token that was created for free is brought onchain, it can be deleted by the original creator of that token, by having that creator sign a message indicating the deletion:

```ts
import { PremintAPI } from "@zoralabs/premint-sdk";
import type { Address, WalletClient } from "viem";
import {createPremintClient} from "@zoralabs/protocol-sdk";
import type {Address, PublicClient, 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 = createPremintClient({ chain: walletClient.chain });
async function deleteCreatedForFreeToken(walletClient: WalletClient) {
const premintClient = createPremintClient({ chain: walletClient.chain! });

// Create premint
const premint = await premintAPI.deletePremint({
// sign a message to delete the premint, and store the deletion
await premintClient.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:
### Minting a token that was created for free (and bringing it onchain):

```ts
import { PremintAPI } from "@zoralabs/premint-sdk";
import type { Address, WalletClient } from "viem";
import {createPremintClient} from "@zoralabs/protocol-sdk";
import type {Address, PublicClient, WalletClient} from "viem";

async function executePremint(
async function mintCreatedForFreeToken(
walletClient: WalletClient,
premintAddress: Address,
premintUID: number,
publicClient: PublicClient,
minterAccount: Address,
) {
const premintAPI = createPremintClient({ chain: walletClient.chain });

return await premintAPI.executePremintWithWallet({
data: premintAPI.getPremintData(premintAddress, premintUID),
walletClient,
const premintClient = createPremintClient({ chain: walletClient.chain! });

const simulateContractParameters = await premintClient.makeMintParameters({
account: minterAccount,
data: await premintClient.getPremintData({
address: "0xf8dA7f53c283d898818af7FB9d98103F559bDac2",
uid: 3,
}),
mintArguments: {
quantityToMint: 1,
mintComment: "",
},
});
}
```

### Deleting a premint:
// simulate the transaction and get any validation errors
const { request } = await publicClient.simulateContract(simulateContractParameters);

```ts
import {PremintAPI} from '@zoralabs/premint-sdk';
import type {Address, WalletClient} from 'viem';
// submit the transaction to the network
const txHash = await walletClient.writeContract(request);

async function deletePremint(walletClient: WalletClient, collection: Address, uid: number) {
const premintAPI = createPremintClient({chain: walletClient.chain});
// wait for the transaction to be complete
const receipt = await publicClient.waitForTransactionReceipt({hash: txHash});

return await premintAPI.deletePremint({
walletClient,
uid,
collection
});
}
const { urls } = await premintClient.getDataFromPremintReceipt(receipt);

```
// block explorer url:
console.log(urls.explorer);
// collect url:
console.log(urls.zoraCollect);
// manage url:
console.log(urls.zoraManage);
}
```
90 changes: 72 additions & 18 deletions packages/protocol-sdk/src/premint/premint-api-client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { post, retries, get } from "../apis/http-api-base";
import {
IHttpClient,
httpClient as defaultHttpClient,
} from "../apis/http-api-base";
import { components, paths } from "../apis/generated/premint-api-types";
import { ZORA_API_BASE } from "../constants";
import { NetworkConfig } from "src/apis/chain-constants";
import { getApiNetworkConfigForChain } from "src/mint/mint-api-client";

type SignaturePostType = paths["/signature"]["post"];
type PremintSignatureRequestBody =
Expand All @@ -22,36 +27,85 @@ type PremintSignatureGetPathParameters =
export type PremintSignatureGetResponse =
SignaturePremintGetType["responses"][200]["content"]["application/json"];

export type PremintCollection = PremintSignatureGetResponse["collection"];

export type BackendChainNames = components["schemas"]["ChainName"];

const postSignature = async (
data: PremintSignatureRequestBody,
): Promise<PremintSignatureResponse> =>
const postSignature = async ({
httpClient: { post, retries } = defaultHttpClient,
...data
}: PremintSignatureRequestBody & {
httpClient?: Pick<IHttpClient, "retries" | "post">;
}): Promise<PremintSignatureResponse> =>
retries(() =>
post<PremintSignatureResponse>(`${ZORA_API_BASE}premint/signature`, data),
);

const getNextUID = async (
path: PremintNextUIDGetPathParameters,
): Promise<PremintNextUIDGetResponse> =>
const getNextUID = async ({
chain_name,
collection_address,
httpClient: { retries, get } = defaultHttpClient,
}: PremintNextUIDGetPathParameters & {
httpClient?: Pick<IHttpClient, "retries" | "get">;
}): Promise<PremintNextUIDGetResponse> =>
retries(() =>
get<PremintNextUIDGetResponse>(
`${ZORA_API_BASE}premint/signature/${path.chain_name}/${path.collection_address}/next_uid`,
`${ZORA_API_BASE}premint/signature/${chain_name}/${collection_address}/next_uid`,
),
);

const getSignature = async (
path: PremintSignatureGetPathParameters,
): Promise<PremintSignatureGetResponse> =>
const getSignature = async ({
collection_address,
uid,
chain_name,
httpClient: { retries, get } = defaultHttpClient,
}: PremintSignatureGetPathParameters & {
httpClient?: Pick<IHttpClient, "retries" | "get">;
}): Promise<PremintSignatureGetResponse> =>
retries(() =>
get<PremintSignatureGetResponse>(
`${ZORA_API_BASE}premint/signature/${path.chain_name}/${path.collection_address}/${path.uid}`,
`${ZORA_API_BASE}premint/signature/${chain_name}/${collection_address}/${uid}`,
),
);

export const PremintAPIClient = {
postSignature,
getSignature,
getNextUID,
};
export { ZORA_API_BASE };
type OmitChainName<T> = Omit<T, "chain_name">;

class PremintAPIClient {
httpClient: IHttpClient;
networkConfig: NetworkConfig;

constructor(chainId: number, httpClient?: IHttpClient) {
this.httpClient = httpClient || defaultHttpClient;
this.networkConfig = getApiNetworkConfigForChain(chainId);
}
postSignature = async (
data: OmitChainName<PremintSignatureRequestBody>,
): Promise<PremintSignatureResponse> =>
postSignature({
...data,
chain_name: this.networkConfig.zoraBackendChainName,
httpClient: this.httpClient,
});

getNextUID = async (
path: OmitChainName<PremintNextUIDGetPathParameters>,
): Promise<PremintNextUIDGetResponse> =>
getNextUID({
...path,
chain_name: this.networkConfig.zoraBackendChainName,
httpClient: this.httpClient,
});

getSignature = async ({
collection_address,
uid,
}: OmitChainName<PremintSignatureGetPathParameters>): Promise<PremintSignatureGetResponse> =>
getSignature({
collection_address,
uid,
chain_name: this.networkConfig.zoraBackendChainName,
httpClient: this.httpClient,
});
}

export { ZORA_API_BASE, PremintAPIClient };
Loading

0 comments on commit a75632a

Please sign in to comment.