diff --git a/sdk/README.md b/sdk/README.md index 6b5f1f23..04e06c5c 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -5,13 +5,13 @@ 1. Install the SDK using npm or yarn: ```bash -npm install @hypercerts-org/sdk +pnpm install @hypercerts-org/sdk ``` or ```bash - yarn add @hypercerts-org/sdk + pnpm add @hypercerts-org/sdk ``` 2. Import the SDK into your project: @@ -24,7 +24,9 @@ import { HypercertClient } from "@hypercerts-org/sdk"; ```js const client = new HypercertClient({ - chain: { id: 11155111 }, // required + environment: "test", + walletClient, // optional, client will default to read-only mode if not provided + publicClient, // optional, can be infered from walletClient if present }); ``` @@ -34,18 +36,16 @@ const client = new HypercertClient({ For example, you can use the `client.mintClaim` method to create a new claim: -```js -const tx = await client.mintClaim(metaData, totalUnits, transferRestriction, overrides); +```ts +const hash = await client.mintHypercert({ + metaData: { ... }, + totalUnits: 1000n, + transferRestriction: TransferRestrictions.AllowAll, +}); ``` This will validate the metadata, store it on IPFS, create a new hypercert on-chain and return a transaction receipt. -You can also use the client to query the subgraph and retrieve which claims an address owns: - -```js -const claims = await client.indexer.fractionsByOwner(owner); -``` - For more information on how to use the SDK, check out the [developer documentation](https://hypercerts.org/docs/developer/) and the [Graph playground](https://thegraph.com/hosted-service/subgraph/hypercerts-admin/hypercerts-testnet). @@ -58,29 +58,21 @@ HypercertClientConfig is a configuration object used when initializing a new ins you to customize the client by setting your own providers or deployments. At it's simplest, you only need to provide `chain.id` to initalize the client in `readonly` mode. -| Field | Type | Description | -| --------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------- | -| `chain` | Object | Partial configuration for the blockchain network. | -| `contractAddress` | String | The address of the deployed contract. | -| `graphName` | String | The name of the subgraph. | -| `easContractAddress` | String | The address of the EAS contract. | -| `publicClient` | Object | The PublicClient is inherently read-only and is used for reading data from the blockchain. | -| `walletClient` | Object | The WalletClient is used for signing and sending transactions. | -| `unsafeForceOverrideConfig` | Boolean | Boolean to force the use of overridden values. | -| `readOnly` | Boolean | Boolean to assert if the client is in read-only mode. | -| `readOnlyReason` | String | Reason for read-only mode. This is optional and can be used for logging or debugging purposes. | -| `indexerEnvironment` | `'test' \| 'production' \| 'all'` | Determines which graphs should be read out when querying | The environment of the indexer. | +| Field | Type | Description | +| -------------- | ------------------------ | -------------------------------------------------------------------------------------------- | +| `environment` | `'test' \| 'production'` | Defines the environment the client will connect with. | +| `deployments` | Object | The deployments of the contracts on various networks. | +| `readOnly` | Boolean | Boolean to assert if the client is in read-only mode. | +| `graphUrl` | String | The URL of the graph endpoint. | +| `publicClient` | Object | The `PublicClient` is inherently read-only and is used for reading data from the blockchain. | +| `walletClient` | Object | The `WalletClient` is used for signing and sending transactions. | ### Read-only mode The SDK client will be in read-only mode if any of the following conditions are true: -- The client was initialized without a walletprovider. -- The contract address is not set. -- The storage layer is in read-only mode. - -If any of these conditions are true, the readonly property of the HypercertClient instance will be set to true, and a -warning message will be logged indicating that the client is in read-only mode. +- The client was initialized without a wallet client. +- The client was initialized with a wallet client connected to a chain that is not supported in the environment. ### Logging @@ -88,41 +80,22 @@ The logger for the SDK uses the log level based on the value of the LOG_LEVEL en determines which log messages are printed to the console. By default, the logger is configured to log messages with a level of info or higher to the console. -## Client modules +## Modules -The `HypercertClient` provides a high-level interface for interacting with the Hypercert ecosystem. The HypercertClient -has three getter methods: `storage`, `indexer`, and `contract`. These methods return instances of the HypercertsStorage, -HypercertIndexer, and HypercertMinter classes, respectively. +### Storage -```js -const { - client: { storage }, -} = new HypercertClient({ chain: { id: 11155111 } }); -``` - -The `storage` is a utility class that provides methods for storing and retrieving Hypercert metadata from IPFS. It is -used by the HypercertClient to store metadata when creating new Hypercerts. +The `storage` module is an utility service for easy access to the hypercerts API. It's built based on the OpenAPI spec +exposed by the hypercerts API. ```js -const { - client: { indexer }, -} = new HypercertClient({ chain: { id: 11155111 } }); -``` + const client = new HypercertClient({ + environment: "test", + walletClient, // optional, client will default to read-only mode if not provided + publicClient, // optional, can be infered from walletClient if present +}); -The `indexer` is a utility class that provides methods for indexing and searching Hypercerts based on various criteria. -It is used by the HypercertClient to retrieve event-based data via the subgraph +const storage = client.storage; -```js -const { - client: { contract }, -} = new HypercertClient({ chain: { id: 11155111 } }); +const storageRequest = { metadata: {...}} +const storageResponse = await client.storage.storeMetadata(storageRequest); ``` - -Finally we have a `contract` that provides methods for interacting with the HypercertMinter smart contract. It is used -by the HypercertClient to create new Hypercerts and retrieve specific on-chain information. - -By providing instances of these classes through the storage, indexer, and contract getters, the HypercertClient allows -developers to easily interact with the various components of the Hypercert system. For example, a developer could use -the storage instance to store metadata for a new Hypercert, the indexer instance to search for existing Hypercerts based -on various criteria, and the contract instance to create new Hypercerts and retrieve existing Hypercerts from the -contract. diff --git a/sdk/package.json b/sdk/package.json index f15e3966..2f6b1141 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@hypercerts-org/sdk", - "version": "2.0.0-alpha.30", + "version": "2.0.0-alpha.31", "description": "SDK for hypercerts protocol", "repository": "git@github.com:hypercerts-org/hypercerts.git", "author": "Hypercerts team", diff --git a/sdk/src/client.ts b/sdk/src/client.ts index 8950f6d8..2dcb917b 100644 --- a/sdk/src/client.ts +++ b/sdk/src/client.ts @@ -57,8 +57,8 @@ export class HypercertClient implements HypercertClientInterface { * * This constructor takes a `config` parameter that is used to configure the client. The `config` parameter should be a `HypercertClientConfig` object. If the public client cannot be connected, it throws a `ClientError`. * - * @param {Partial} config - The configuration options for the client. - * @throws {ClientError} Will throw a `ClientError` if the public client cannot be connected. + * @param config - The configuration options for the client. + * @throws Will throw a `ClientError` if the public client cannot be connected. */ constructor(config: Partial) { this._config = getConfig(config); @@ -68,17 +68,36 @@ export class HypercertClient implements HypercertClientInterface { this.readOnly = this._config.readOnly; } + /** + * Checks if a hypercert or fraction is on the connected chain. + * + * This method verifies if the provided claim or fraction ID is on the chain that the wallet client is connected to. + * + * @param claimOrFractionId - The ID of the claim or fraction to check. + * @returns A boolean indicating whether the claim or fraction is on the connected chain. + */ isHypercertsOrFractionOnConnectedChain = (claimOrFractionId: string) => { const connectedChain = this._walletClient?.chain?.id; return isClaimOnChain(claimOrFractionId, connectedChain); }; + /** + * Checks if a claim or fraction is on the connected chain. + * + * This method is an alias for `isHypercertsOrFractionOnConnectedChain` and performs the same check. + * + * @param claimOrFractionId - The ID of the claim or fraction to check. + * @returns A boolean indicating whether the claim or fraction is on the connected chain. + */ isClaimOrFractionOnConnectedChain = (claimOrFractionId: string) => { return this.isHypercertsOrFractionOnConnectedChain(claimOrFractionId); }; /** * Gets the config for the client. + * + * This getter method returns the configuration object for the `HypercertClient`. + * * @returns The client config. */ get config(): Partial { @@ -86,16 +105,24 @@ export class HypercertClient implements HypercertClientInterface { } /** - * Gets the storage layer for the client. - * @returns The storage layer. + * Gets the storage service for the client. + * + * This getter method returns the storage service used by the `HypercertClient`. + * + * @returns The hypercerts storage service. */ get storage(): HypercertStorage { return this._storage; } /** - * Gets the contract addresses and graph urls for the provided `chainId` or `environment`. When both are provided, chainId takes precedence. If none is provided, it defaults to the configured environment. - * @returns The addresses, graph name and graph url + * Retrieves the contract addresses and GraphQL URLs for the provided `chainId` or `environment`. + * + * When both `chainId` and `environment` are provided, `chainId` takes precedence. If neither is provided, it defaults to the configured environment. + * + * @param chainId - The chain ID for which to retrieve deployments. + * @param environment - The environment for which to retrieve deployments. + * @returns The addresses, graph name, and graph URL for the specified chain ID or environment. */ getDeployments = ({ chainId, environment }: { chainId?: SupportedChainIds; environment?: Environment }) => { if (chainId) return getDeploymentsForChainId(chainId); @@ -118,6 +145,20 @@ export class HypercertClient implements HypercertClientInterface { return await this.mintHypercert({ metaData, totalUnits, transferRestriction, allowList, overrides }); }; + /** + * Mints a new hypercert. + * + * This function handles the minting process of a hypercert, including fetching and parsing the allowlist if provided, + * validating and storing metadata, and submitting the minting request. + * + * @param metaData - The metadata for the hypercert. + * @param totalUnits - The total units of the hypercert. + * @param transferRestriction - The transfer restrictions for the hypercert. + * @param allowList - The allowlist for the hypercert, either as a URI to a CSV file or an array of allowlist entries. + * @param overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the minting request. + * @throws Will throw a `ClientError` if any validation or request submission fails. + */ mintHypercert = async ({ metaData, totalUnits, transferRestriction, allowList, overrides }: MintParams) => { const { account } = this.getConnected(); @@ -189,9 +230,7 @@ export class HypercertClient implements HypercertClientInterface { }; /** - * Gets the TransferRestrictions for a claim. - * - * This method first retrieves the read contract using the `getContract` method. It then simulates a contract call to the `readTransferRestriction` function with the provided fraction ID. + * Gets the {TransferRestrictions} for a claim. * * @param fractionId * @returns a Promise that resolves to the applicable transfer restrictions. @@ -202,6 +241,18 @@ export class HypercertClient implements HypercertClientInterface { return await readContract.read.readTransferRestriction([fractionId]).then((res) => res as TransferRestrictions); }; + /** + * Transfers a fraction to a specified address. + * + * This function handles the transfer of a fraction from the connected account to the specified address. + * + * @param params - The parameters for the transfer. + * @param params.fractionId - The ID of the fraction to transfer. + * @param params.to - The address to transfer the fraction to. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the transfer request. + * @throws Will throw a `ClientError` if the request fails. + */ transferFraction = async ({ fractionId, to, overrides }: TransferParams) => { const { account } = this.getConnected(); @@ -215,6 +266,18 @@ export class HypercertClient implements HypercertClientInterface { return this.submitRequest(request); }; + /** + * Transfers multiple fractions to a specified address. + * + * This function handles the batch transfer of multiple fractions from the connected account to the specified address. + * + * @param params - The parameters for the batch transfer. + * @param params.fractionIds - The IDs of the fractions to transfer. + * @param params.to - The address to transfer the fractions to. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the batch transfer request. + * @throws Will throw a `ClientError` if the request fails. + */ batchTransferFractions = async ({ fractionIds, to, overrides }: BatchTransferParams) => { const { account } = this.getConnected(); @@ -241,25 +304,38 @@ export class HypercertClient implements HypercertClientInterface { return await this.mintHypercert({ metaData, totalUnits, transferRestriction, allowList, overrides }); }; + /** + * Splits a fraction into multiple fractions. + * + * This function handles the splitting of a fraction into multiple smaller fractions. + * It verifies the ownership of the fraction and ensures the sum of the new fractions equals the total units of the original fraction. + * + * @param params - The parameters for the split operation. + * @param params.fractionId - The ID of the fraction to split. + * @param params.fractions - An array of units representing the new fractions. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the split request or undefined. + * @throws Will throw a `ClientError` if the fraction is not owned by the signer or if the sum of the new fractions does not equal the total units. + */ splitFraction = async ({ fractionId, fractions, overrides, }: SplitFractionParams): Promise<`0x${string}` | undefined> => { const { account } = this.getConnected(); - const readContract = this._getContract(); const fractionOwner = (await readContract.read.ownerOf([fractionId])) as `0x${string}`; const totalUnits = (await readContract.read.unitsOf([fractionId])) as bigint; - if (fractionOwner.toLowerCase() !== account?.address.toLowerCase()) + if (fractionOwner.toLowerCase() !== account?.address.toLowerCase()) { throw new ClientError("Claim is not owned by the signer", { signer: account?.address, fractionOwner }); + } - // check if the sum of the fractions is equal to the total units const sumFractions = fractions.reduce((a, b) => a + b, 0n); - if (sumFractions != totalUnits) + if (sumFractions !== totalUnits) { throw new ClientError("Sum of fractions is not equal to the total units", { totalUnits, sumFractions }); + } const request = await this.simulateRequest( account, @@ -267,7 +343,6 @@ export class HypercertClient implements HypercertClientInterface { [account?.address, fractionId, fractions], overrides, ); - return this.submitRequest(request); }; @@ -278,13 +353,27 @@ export class HypercertClient implements HypercertClientInterface { return this.splitFraction({ fractionId, fractions, overrides }); }; + /** + * Merges multiple fractions into a single fraction. + * + * This function handles the merging of multiple fractions from the connected account. + * It verifies the ownership of each fraction and ensures all fractions are owned by the signer. + * + * @param params - The parameters for the merge operation. + * @param params.fractionIds - The IDs of the fractions to merge. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the merge request. + * @throws Will throw a `ClientError` if one or more fractions are not owned by the signer. + */ mergeFractions = async ({ fractionIds, overrides }: MergeFractionsParams) => { const { account } = this.getConnected(); - const readContract = this._getContract(); const fractions = await Promise.all( - fractionIds.map(async (id) => ({ id, owner: (await readContract.read.ownerOf([id])) as `0x${string}` })), + fractionIds.map(async (id) => ({ + id, + owner: (await readContract.read.ownerOf([id])) as `0x${string}`, + })), ); const notOwned = fractions.filter((fraction) => fraction.owner.toLowerCase() !== account?.address.toLowerCase()); @@ -308,6 +397,18 @@ export class HypercertClient implements HypercertClientInterface { return this.mergeFractions({ fractionIds, overrides }); }; + /** + * Burns a fraction. + * + * This function handles the burning of a fraction from the connected account. + * It verifies the ownership of the fraction before proceeding with the burn operation. + * + * @param params - The parameters for the burn operation. + * @param params.fractionId - The ID of the fraction to burn. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the burn request. + * @throws Will throw a `ClientError` if the fraction is not owned by the signer. + */ burnFraction = async ({ fractionId, overrides }: BurnFractionParams) => { const { account } = this.getConnected(); @@ -331,6 +432,21 @@ export class HypercertClient implements HypercertClientInterface { return this.burnFraction({ fractionId: claimId, overrides }); }; + /** + * Claims a fraction from an allowlist. + * + * This function handles the claiming of a fraction from an allowlist for the connected account. + * It verifies the Merkle proof if a root is provided and then submits the minting request. + * + * @param params - The parameters for the claim operation. + * @param params.hypercertTokenId - The ID of the hypercert token to claim. + * @param params.units - The number of units to claim. + * @param params.proof - The Merkle proof for the claim. + * @param params.root - The Merkle root for the allowlist. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the claim request. + * @throws Will throw an `InvalidOrMissingError` if no wallet address is found. + */ claimFractionFromAllowlist = async ({ hypercertTokenId, units, @@ -340,12 +456,11 @@ export class HypercertClient implements HypercertClientInterface { }: ClaimFractionFromAllowlistParams) => { const { account } = this.getConnected(); - //verify the proof using the OZ merkle tree library - if (root && root.length > 0) { + if (root?.length) { if (!account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); verifyMerkleProof( root.toString(), - account?.address, + account.address, units, proof.map((p) => p.toString()), ); @@ -354,10 +469,9 @@ export class HypercertClient implements HypercertClientInterface { const request = await this.simulateRequest( account, "mintClaimFromAllowlist", - [account?.address, proof, hypercertTokenId, units], + [account.address, proof, hypercertTokenId, units], overrides, ); - return this.submitRequest(request); }; @@ -374,6 +488,21 @@ export class HypercertClient implements HypercertClientInterface { return this.claimFractionFromAllowlist({ hypercertTokenId: claimId, units, proof, root, overrides }); }; + /** + * Claims multiple fractions from multiple allowlists. + * + * This function handles the batch claiming of fractions from multiple allowlists for the connected account. + * It verifies the Merkle proofs if roots are provided and then submits the batch minting request. + * + * @param params - The parameters for the batch claim operation. + * @param params.hypercertTokenIds - The IDs of the hypercert tokens to claim. + * @param params.units - The number of units to claim for each token. + * @param params.proofs - The Merkle proofs for each claim. + * @param params.roots - The Merkle roots for the allowlists. + * @param params.overrides - Optional overrides for the transaction. + * @returns A promise that resolves to the transaction hash of the batch claim request. + * @throws Will throw an `InvalidOrMissingError` if no wallet address is found. + */ batchClaimFractionsFromAllowlists = async ({ hypercertTokenIds, units, @@ -383,13 +512,11 @@ export class HypercertClient implements HypercertClientInterface { }: BatchClaimFractionsFromAllowlistsParams) => { const { account } = this.getConnected(); - //verify the proof using the OZ merkle tree library - if (roots && roots.length > 0) { + if (roots?.length) { if (!account?.address) throw new InvalidOrMissingError("No wallet address found, are you connected?"); - verifyMerkleProofs( roots.map((r) => r.toString()), - account?.address, + account.address, units, proofs.map((p) => p.map((p) => p.toString())), ); @@ -398,7 +525,7 @@ export class HypercertClient implements HypercertClientInterface { const request = await this.simulateRequest( account, "batchMintClaimsFromAllowlists", - [account?.address, proofs, hypercertTokenIds, units], + [account.address, proofs, hypercertTokenIds, units], overrides, ); @@ -418,12 +545,17 @@ export class HypercertClient implements HypercertClientInterface { return this.batchClaimFractionsFromAllowlists({ hypercertTokenIds: claimIds, units, proofs, roots, overrides }); }; + /** + * Retrieves claim stored data from a transaction hash. + * + * This function fetches the stored data associated with a given transaction hash using the public client. + * + * @param hash - The transaction hash to retrieve the claim stored data for. + * @returns A promise that resolves to the claim stored data. + */ getClaimStoredDataFromTxHash = async (hash: `0x${string}`) => { const { publicClient } = this.getConnected(); - - const { data, errors, success } = await getClaimStoredDataFromTxHash(publicClient, hash); - - return { data, errors, success }; + return await getClaimStoredDataFromTxHash(publicClient, hash); }; private _getContract = () => { @@ -499,9 +631,9 @@ export class HypercertClient implements HypercertClientInterface { * * This method submits a contract request using the `writeContract` method of the wallet client. If the request fails, it throws a `ClientError`. * - * @param {any} request - The contract request to submit. - * @returns {Promise<`0x${string}`>} A promise that resolves to the hash of the submitted request. - * @throws {ClientError} Will throw a `ClientError` if the request fails. + * @param request - The contract request to submit. + * @returns a promise that resolves to the hash of the submitted request. + * @throws will throw a `ClientError` if the request fails. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any private submitRequest = async (request: any) => { diff --git a/sdk/src/storage.ts b/sdk/src/storage.ts index 0a0f7c35..69432001 100644 --- a/sdk/src/storage.ts +++ b/sdk/src/storage.ts @@ -12,8 +12,11 @@ import { ENDPOINTS } from "./constants"; import { HypercertStorage } from "./types/storage"; /** - * An utility methods that provides storage functionality for hypercerts metadata and allow lists. + * An utility service that provides storage functionality for hypercerts metadata and allow lists by exposing a set of methods to interact with the storage service API. * + * @param environment - The environment in which the storage will operate. + * @param config - Optional Axios configuration for the request. + * @returns An object containing methods to store metadata and allowlists. */ export const getStorage = ({ environment, @@ -31,10 +34,30 @@ export const getStorage = ({ }; return { + /** + * Stores metadata for a hypercert. + * @param request - The request object containing metadata to be stored. + * @param config - Optional Axios configuration for the request. + * @returns A promise that resolves when the metadata is stored. + */ storeMetadata: async (request: StoreMetadataRequest, config: AxiosRequestConfig = {}) => storeMetadata(request, { ..._config, ...config }), + + /** + * Stores an allowlist for a hypercert. + * @param request - The request object containing the allowlist to be stored. + * @param config - Optional Axios configuration for the request. + * @returns A promise that resolves when the allowlist is stored. + */ storeAllowlist: async (request: StoreAllowListRequest, config: AxiosRequestConfig = {}) => storeAllowList(request, { ..._config, ...config }), + + /** + * Stores metadata and an allowlist for a hypercert. + * @param request - The request object containing metadata and allowlist to be stored. + * @param config - Optional Axios configuration for the request. + * @returns A promise that resolves when the metadata and allowlist are stored. + */ storeMetadataWithAllowlist: async (request: StoreMetadataWithAllowlistRequest, config: AxiosRequestConfig = {}) => storeMetadataWithAllowlist(request, { ..._config, ...config }), }; diff --git a/sdk/src/types/client.ts b/sdk/src/types/client.ts index cc981104..bbae7ba3 100644 --- a/sdk/src/types/client.ts +++ b/sdk/src/types/client.ts @@ -53,14 +53,29 @@ export type Deployment = { * Configuration options for the Hypercert client. */ export type HypercertClientConfig = { - /** The environment to run the indexer in. This can be either production, test or all. Defaults to test */ + /** + * The environment to run the indexer in. This can be either production, test or all. Defaults to test. + */ environment: Environment; + /** + * The deployments of the contracts on various networks. + */ deployments: { [k: string]: Deployment }; - /** Boolean to assert if the client is in readOnly mode */ + /** + * Boolean to assert if the client is in read-only mode. + */ readOnly: boolean; + /** + * The URL of the graph endpoint. + */ graphUrl: string; - /** The PublicClient is inherently read-only */ + /** + * The PublicClient is inherently read-only. + */ publicClient?: PublicClient; + /** + * The WalletClient is used for signing and sending transactions. + */ walletClient?: WalletClient; }; diff --git a/sdk/src/types/hypercerts.ts b/sdk/src/types/hypercerts.ts index 82f03c55..e733f63d 100644 --- a/sdk/src/types/hypercerts.ts +++ b/sdk/src/types/hypercerts.ts @@ -1,10 +1,5 @@ /** * Represents the possible transfer restrictions of a claim matching the hypercerts protocol. - * - * @typedef {Object} TransferRestrictions - * @property {number} AllowAll - Represents no restrictions on the transfer of the claim. - * @property {number} DisallowAll - Represents complete restriction on the transfer of the claim. - * @property {number} FromCreatorOnly - Represents that the claim can only be transferred by its creator. */ export const TransferRestrictions = { AllowAll: 0, @@ -16,10 +11,6 @@ export type TransferRestrictions = (typeof TransferRestrictions)[keyof typeof Tr /** * Represents an entry in an allowlist. - * - * @typedef {Object} AllowlistEntry - * @property {string} address - The address of the entry. - * @property {bigint} units - The units associated with the entry. */ export type AllowlistEntry = { address: string; diff --git a/sdk/src/utils/config.ts b/sdk/src/utils/config.ts index 9c190527..ce4fdd65 100644 --- a/sdk/src/utils/config.ts +++ b/sdk/src/utils/config.ts @@ -18,10 +18,10 @@ import { createPublicClient, http } from "viem"; * - 84532: Base Sepolia * - 8453: Base Mainnet * - * @param {Partial} overrides - An object containing any configuration values to override. This should be a partial HypercertClientConfig object. - * @returns {Partial} The final configuration object for the Hypercert client. - * @throws {InvalidOrMissingError} Will throw an `InvalidOrMissingError` if the `unsafeForceOverrideConfig` flag is set but the required overrides are not provided. - * @throws {UnsupportedChainError} Will throw an `UnsupportedChainError` if the default configuration for the provided chain ID is missing. + * @param config - An object containing any configuration values to override. This should be a partial HypercertClientConfig object. + * @returns The final configuration object for the Hypercert client. + * @throws InvalidOrMissingError - Will throw an `InvalidOrMissingError` if the `unsafeForceOverrideConfig` flag is set but the required overrides are not provided. + * @throws UnsupportedChainError - Will throw an `UnsupportedChainError` if the default configuration for the provided chain ID is missing. */ export const getConfig = ( config: Partial>, @@ -59,6 +59,17 @@ export const getConfig = ( return _config; }; +/** + * Retrieves the deployments for a given environment. + * + * This function filters known deployments object to find deployments that match the provided environment. + * It returns deployments for testnets if the environment is "test" and for mainnets if the environment is "production". + * If no deployments are found, it throws an error. + * + * @param environment - The environment for which to retrieve deployments. + * @returns An object containing the deployments for the specified environment. + * @throws Will throw an error if no deployments are found for the given environment. + */ export const getDeploymentsForEnvironment = (environment: Environment) => { const deployments = Object.fromEntries( Object.entries(DEPLOYMENTS).filter(([_, deployment]) => { @@ -79,6 +90,16 @@ export const getDeploymentsForEnvironment = (environment: Environment) => { return deployments; }; +/** + * Retrieves the deployments for a given chain ID. + * + * This function filters known deployments to find deployments that match the provided chain ID. + * If no deployments are found, it throws an error. + * + * @param chainId - The chain ID for which to retrieve deployments. + * @returns An object containing the deployments for the specified chain ID. + * @throws Will throw an error if no deployments are found for the given chain ID. + */ export const getDeploymentsForChainId = (chainId: SupportedChainIds) => { logger.info("Indexer", "getDeploymentsForChainId", { chainId }); @@ -97,6 +118,16 @@ export const getDeploymentsForChainId = (chainId: SupportedChainIds) => { return deployments; }; +/** + * Retrieves the environment configuration. + * + * This function checks if the environment is provided in the configuration object and validates it against the available endpoints. + * If the environment is missing or invalid, it throws an error. + * + * @param config - The configuration object containing the environment. + * @returns An object containing the validated environment. + * @throws Will throw an error if the environment is missing or invalid. + */ const getEnvironment = (config: Partial) => { const environment = config.environment; @@ -107,6 +138,16 @@ const getEnvironment = (config: Partial) => { return { environment }; }; +/** + * Retrieves the GraphQL URL for the given environment. + * + * This function checks if the environment is provided in the configuration object and validates it against the available endpoints. + * If the environment is missing or invalid, it throws an error. + * + * @param config - The configuration object containing the environment. + * @returns An object containing the GraphQL URL for the specified environment. + * @throws Will throw an error if the environment is missing or invalid. + */ const getGraphUrl = (config: Partial) => { const environment = config.environment; @@ -117,6 +158,15 @@ const getGraphUrl = (config: Partial) => { return { graphUrl: `${ENDPOINTS[environment]}/v1/graphql` }; }; +/** + * Retrieves the wallet client from the configuration. + * + * This function checks if the wallet client is provided in the configuration object. + * If the wallet client is missing, the client will default to readonly mode. + * + * @param config - The configuration object containing the wallet client. + * @returns An object containing the wallet client. + */ const getWalletClient = (config: Partial) => { const walletClient = config.walletClient; @@ -127,6 +177,12 @@ const getWalletClient = (config: Partial) => { return { walletClient }; }; +/** + * Retrieves the public client from the configuration. + * + * @param config - The configuration object containing the public client. + * @returns An object containing the public client. + */ const getPublicClient = (config: Partial) => { return { publicClient: config.publicClient }; }; diff --git a/sdk/test/client/minting.test.ts b/sdk/test/client/minting.test.ts index 128990cd..391d86c1 100644 --- a/sdk/test/client/minting.test.ts +++ b/sdk/test/client/minting.test.ts @@ -73,7 +73,11 @@ describe("mintClaim in HypercertClient", () => { writeSpy = writeSpy.resolves(mintClaimResult); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const hash = await client.mintClaim(formattedData!, 1000n, TransferRestrictions.AllowAll); + const hash = await client.mintHypercert({ + metaData: formattedData!, + totalUnits: 1000n, + transferRestriction: TransferRestrictions.AllowAll, + }); expect(isHex(hash)).to.be.true; expect(readSpy.callCount).to.equal(0); @@ -84,7 +88,12 @@ describe("mintClaim in HypercertClient", () => { try { mocks.storeMetadata.mockRejectedValue(new MalformedDataError("Invalid metadata.")); - await client.mintClaim({} as HypercertMetadata, 1000n, TransferRestrictions.AllowAll); + await client.mintHypercert({ + metaData: {} as HypercertMetadata, + totalUnits: 1000n, + transferRestriction: TransferRestrictions.AllowAll, + }); + expect.fail("Should throw MalformedDataError"); } catch (e) { console.log(e); @@ -106,10 +115,13 @@ describe("mintClaim in HypercertClient", () => { let hash; try { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - hash = await client.mintClaim(formattedData!, 1000n, TransferRestrictions.AllowAll, undefined, { - gasPrice: "FALSE_VALUE" as unknown as bigint, + hash = await client.mintHypercert({ + metaData: formattedData!, + totalUnits: 1000n, + transferRestriction: TransferRestrictions.AllowAll, + overrides: { gasPrice: "FALSE_VALUE" as unknown as bigint }, }); + expect.fail("Should throw Error"); } catch (e) { expect(e).to.be.instanceOf(ContractError); @@ -117,8 +129,12 @@ describe("mintClaim in HypercertClient", () => { expect(error.message).to.equal("Contract returned unparsable error. Inspect payload for returned data."); } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - hash = await client.mintClaim(formattedData!, 1000n, TransferRestrictions.AllowAll, undefined, { gasPrice: 100n }); + hash = await client.mintHypercert({ + metaData: formattedData!, + totalUnits: 1000n, + transferRestriction: TransferRestrictions.AllowAll, + overrides: { gasPrice: 100n }, + }); expect(isHex(hash)).to.be.true; expect(readSpy.callCount).to.equal(0);