kamiweb3-sdk
Version:
TypeScript SDK for KAMI721-C, KAMI721-AC, and KAMI1155-C smart contracts
398 lines • 17.9 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ERC721ACWrapper = void 0;
const ethers_1 = require("ethers");
const types_1 = require("../types");
const KAMI721AC_json_1 = __importDefault(require("../abis/KAMI721AC.json"));
const ethers = __importStar(require("ethers"));
/**
* Wraps an instance of the KAMI721AC contract (standard or upgradeable proxy) to provide typed methods.
*/
class ERC721ACWrapper {
/**
* Creates an instance of ERC721ACWrapper.
* @param address The address of the standard contract or the proxy contract.
* @param signerOrProvider A Signer (for transactions) or Provider (for read-only).
* @param contractAbi (Optional) The ABI to use. Defaults to the standard KAMI721AC ABI. Provide the KAMI721ACUpgradeable ABI when attaching to a proxy.
*/
constructor(address, signerOrProvider, contractAbi) {
// Use provided ABI or default to standard KAMI721AC ABI
this.abi = contractAbi || KAMI721AC_json_1.default.abi;
if (!this.abi || this.abi.length === 0) {
if (!contractAbi && (!KAMI721AC_json_1.default || !KAMI721AC_json_1.default.abi)) {
throw new Error('Default KAMI721AC ABI not found or invalid.');
}
else {
throw new Error('Provided ABI is invalid or ABI not found.');
}
}
this.contract = new ethers_1.Contract(address.toString(), this.abi, signerOrProvider);
this.address = address.toString();
}
// === Core ERC721 Functions (including ERC721A overrides) ===
/**
* Returns the number of tokens in `owner`'s account.
* @throws {Error} If owner is the zero address.
*/
async balanceOf(owner) {
if (owner === ethers_1.ZeroAddress)
throw new Error('ERC721: balance query for the zero address');
return this.contract.getFunction('balanceOf')(owner);
}
/**
* Returns the owner of the `tokenId` token.
* @throws {Error} If the token does not exist.
*/
async ownerOf(tokenId) {
return this.contract.getFunction('ownerOf')(tokenId);
}
/**
* Safely transfers `tokenId` token from `from` to `to`.
* @throws {Error} If caller is not owner nor approved, or if `to` is zero address.
*/
async safeTransferFrom(from, to, tokenId, data = '0x', overrides = {}) {
this.requireSigner();
if (to === ethers_1.ZeroAddress)
throw new Error('ERC721: transfer to the zero address');
// ERC721A uses the same signatures for safeTransferFrom
if (data && data !== '0x' && ethers.getBytes(data).length > 0) {
return this.contract.getFunction('safeTransferFrom(address,address,uint256,bytes)')(from, to, tokenId, data, overrides);
}
else {
return this.contract.getFunction('safeTransferFrom(address,address,uint256)')(from, to, tokenId, overrides);
}
}
/**
* Transfers `tokenId` token from `from` to `to`.
* Note: Usage of this method is discouraged, use `safeTransferFrom` whenever possible.
* @throws {Error} If caller is not owner nor approved, or if `to` is zero address.
*/
async transferFrom(from, to, tokenId, overrides = {}) {
this.requireSigner();
if (to === ethers_1.ZeroAddress)
throw new Error('ERC721: transfer to the zero address');
return this.contract.getFunction('transferFrom')(from, to, tokenId, overrides);
}
/**
* Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
* @throws {Error} If `to` is the zero address.
*/
async approve(to, tokenId, overrides = {}) {
this.requireSigner();
if (to === ethers_1.ZeroAddress)
throw new Error('ERC721: approve to the zero address');
return this.contract.getFunction('approve')(to, tokenId, overrides);
}
/**
* Returns the account approved for `tokenId` token.
* @throws {Error} If the token does not exist.
*/
async getApproved(tokenId) {
return this.contract.getFunction('getApproved')(tokenId);
}
/**
* Approve or remove `operator` as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller.
*/
async setApprovalForAll(operator, approved, overrides = {}) {
this.requireSigner();
return this.contract.getFunction('setApprovalForAll')(operator, approved, overrides);
}
/**
* Returns if the `operator` is allowed to manage all of the assets of `owner`.
*/
async isApprovedForAll(owner, operator) {
return this.contract.getFunction('isApprovedForAll')(owner, operator);
}
/**
* Returns the token collection name.
*/
async name() {
return this.contract.getFunction('name')();
}
/**
* Returns the token collection symbol.
*/
async symbol() {
return this.contract.getFunction('symbol')();
}
/**
* Returns the Uniform Resource Identifier (URI) for `tokenId` token.
* @throws {Error} If the token does not exist.
*/
async tokenURI(tokenId) {
return this.contract.getFunction('tokenURI')(tokenId);
}
/**
* Returns the total amount of tokens minted in the contract.
* (ERC721A provides this)
*/
async totalSupply() {
return this.contract.getFunction('totalSupply')();
}
/**
* Returns the next token ID to be minted.
* (Available in ERC721A-based contracts like KAMI721AC)
*/
async nextTokenId() {
return this.contract.getFunction('nextTokenId')();
}
// Note: ERC721A does not include tokenOfOwnerByIndex or tokenByIndex
// It might include view functions like _numberMinted(address), _numberBurned(address), startTokenId()
// Add them here if needed based on detailed ABI review or usage requirements.
// Example:
// async numberMinted(owner: AddressLike): Promise<bigint> {
// return this.contract.getFunction('_numberMinted')(owner);
// }
// === ERC2981 Royalty Standard ===
/**
* Returns the royalty information for a given token ID and sale price.
* @throws {Error} If token does not exist.
*/
async royaltyInfo(tokenId, salePrice) {
const [receiver, royaltyAmount] = await this.contract.getFunction('royaltyInfo')(tokenId, salePrice);
return { receiver, royaltyAmount };
}
// === KAMI Core Functions ===
/**
* Mints one or more new NFTs to the caller's address.
* Requires the sender to have approved the contract for the total USDC cost.
* @param quantity The number of NFTs to mint (must be > 0).
* @param overrides Optional transaction overrides.
* @returns A promise that resolves to the transaction response.
*/
async mint(quantity, overrides = {}) {
this.requireSigner();
const quant = BigInt(quantity.toString());
if (quant <= 0)
throw new Error('Quantity must be greater than zero');
// KAMI721AC ABI confirms mint(uint256 quantity)
return this.contract.getFunction('mint')(quant, overrides);
}
/**
* Allows users to claim tokens (e.g., airdrop) to the caller's address.
* Requires the sender to have approved the contract for the total USDC cost.
* Assumes claim conditions are handled internally or off-chain.
* @param quantity The number of tokens to claim (must be > 0).
* @param overrides Optional transaction overrides.
* @returns A promise that resolves to the transaction response.
*/
async claim(quantity, overrides = {}) {
this.requireSigner();
const quant = BigInt(quantity.toString());
if (quant <= 0)
throw new Error('Quantity must be greater than zero');
// KAMI721AC ABI confirms claim(uint256 quantity)
return this.contract.getFunction('claim')(quant, overrides);
}
/**
* Sells an NFT from the owner (or approved operator) to a buyer.
* Requires seller approval and buyer USDC allowance.
* @throws {Error} If `to` is the zero address.
* @param to The address of the buyer.
* @param tokenId The ID of the token being sold.
* @param salePrice The price in the smallest unit of USDC.
* @param overrides Optional transaction overrides.
* @returns A promise that resolves to the transaction response.
*/
async sellToken(to, tokenId, salePrice, overrides = {}) {
this.requireSigner();
if (to === ethers_1.ZeroAddress)
throw new Error('Cannot sell token to the zero address');
return this.contract.getFunction('sellToken')(to, tokenId, salePrice, overrides);
}
// === KAMI Royalty Management ===
/** Sets default mint royalties. Requires OWNER_ROLE. */
async setMintRoyalties(royalties, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
return this.contract.getFunction('setMintRoyalties')(royalties, overrides);
}
/** Sets default transfer royalties. Requires OWNER_ROLE. */
async setTransferRoyalties(royalties, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
return this.contract.getFunction('setTransferRoyalties')(royalties, overrides);
}
/** Sets token-specific mint royalties. Requires OWNER_ROLE. */
async setTokenMintRoyalties(tokenId, royalties, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
return this.contract.getFunction('setTokenMintRoyalties')(tokenId, royalties, overrides);
}
/** Sets token-specific transfer royalties. Requires OWNER_ROLE. */
async setTokenTransferRoyalties(tokenId, royalties, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
return this.contract.getFunction('setTokenTransferRoyalties')(tokenId, royalties, overrides);
}
/** Gets mint royalty receivers for a token. */
async getMintRoyaltyReceivers(tokenId) {
// Consider adding ownerOf check if needed before calling
return this.contract.getFunction('getMintRoyaltyReceivers')(tokenId);
}
/** Gets transfer royalty receivers for a token. */
async getTransferRoyaltyReceivers(tokenId) {
return this.contract.getFunction('getTransferRoyaltyReceivers')(tokenId);
}
// === KAMI Configuration ===
/** Sets the mint price. Requires OWNER_ROLE. */
async setMintPrice(newMintPrice, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
return this.contract.getFunction('setMintPrice')(newMintPrice, overrides);
}
/** Gets the current mint price. */
async getMintPrice() {
return this.contract.getFunction('getMintPrice')();
}
/** Sets the platform commission percentage and address. Requires OWNER_ROLE. */
async setPlatformCommission(newPercentage, newPlatformAddress, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
if (newPlatformAddress === ethers_1.ZeroAddress)
throw new Error('Platform address cannot be the zero address');
return this.contract.getFunction('setPlatformCommission')(newPercentage, newPlatformAddress, overrides);
}
/** Gets the current platform address for commissions. */
async getPlatformAddress() {
return this.contract.getFunction('getPlatformAddress')();
}
/** Gets the current platform commission percentage (basis points). */
async getPlatformCommissionPercentage() {
return this.contract.getFunction('getPlatformCommissionPercentage')();
}
/** Sets the base URI for metadata. Requires OWNER_ROLE. */
async setBaseURI(baseURI, overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.OWNER_ROLE);
return this.contract.getFunction('setBaseURI')(baseURI, overrides);
}
/** Gets the current base URI for metadata. */
async getBaseURI() {
return this.contract.getFunction('getBaseURI')();
}
/** Gets the address of the USDC contract used. */
async usdc() {
return this.contract.getFunction('usdc')();
}
// === KAMI Administrative ===
/** Pauses the contract. Requires PAUSER_ROLE. */
async pause(overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.PAUSER_ROLE);
return this.contract.getFunction('pause')(...[], overrides);
}
/** Returns true if the contract is paused. */
async paused() {
return this.contract.getFunction('paused')();
}
/** Unpauses the contract. Requires PAUSER_ROLE. */
async unpause(overrides = {}) {
this.requireSigner();
await this.requireRole(types_1.PAUSER_ROLE);
return this.contract.getFunction('unpause')(...[], overrides);
}
/** Burns (destroys) a specific token. Requires caller to be owner or approved. */
async burn(tokenId, overrides = {}) {
this.requireSigner();
// KAMI721AC ABI uses burn(tokenId), not burn(quantity)
// Contract internally checks ownership/approval
return this.contract.getFunction('burn')(tokenId, overrides);
}
// === Access Control ===
/** Checks if an account has a specific role. */
async hasRole(role, account) {
return this.contract.getFunction('hasRole')(role, account);
}
/** Gets the admin role for a specific role. */
async getRoleAdmin(role) {
return this.contract.getFunction('getRoleAdmin')(role);
}
/** Grants a role to an account. Requires caller to have the admin role for the role being granted. */
async grantRole(role, account, overrides = {}) {
this.requireSigner();
const adminRole = await this.getRoleAdmin(role);
await this.requireRole(adminRole, `Caller must have admin role (${adminRole}) to grant role ${role}`);
return this.contract.getFunction('grantRole')(role, account, overrides);
}
/** Revokes a role from an account. Requires caller to have the admin role for the role being revoked. */
async revokeRole(role, account, overrides = {}) {
this.requireSigner();
const adminRole = await this.getRoleAdmin(role);
await this.requireRole(adminRole, `Caller must have admin role (${adminRole}) to revoke role ${role}`);
return this.contract.getFunction('revokeRole')(role, account, overrides);
}
/** Renounces a role for the caller's own account. */
async renounceRole(role, overrides = {}) {
// Note: The ABI has renounceRole(bytes32 role, address account),
// but OZ's standard implementation prevents renouncing for others.
// We get the caller's address to pass as the account argument.
const signer = this.requireSigner();
const callerAddress = await signer.getAddress();
return this.contract.getFunction('renounceRole')(role, callerAddress, overrides);
}
// === Helper Methods ===
requireSigner() {
const runner = this.contract.runner;
if (!runner || runner.provider === null) {
throw new Error('A signer is required for this operation.');
}
return runner;
}
async requireRole(role, errorMessage) {
const signer = this.requireSigner();
const address = await signer.getAddress();
if (!(await this.hasRole(role, address))) {
throw new Error(errorMessage || `Caller does not have required role: ${role}`);
}
}
/**
* Connects a different signer or provider to the contract wrapper.
* Preserves the ABI used when the original wrapper was created.
* @param signerOrProvider The new signer or provider.
* @returns A new ERC721ACWrapper instance connected with the new signer/provider.
*/
connect(signerOrProvider) {
// Pass the existing ABI to the new instance
return new ERC721ACWrapper(this.address, signerOrProvider, this.abi);
}
}
exports.ERC721ACWrapper = ERC721ACWrapper;
//# sourceMappingURL=ERC721ACWrapper.js.map