diff --git a/packages/engine/paima-funnel/src/cde/erc1155.ts b/packages/engine/paima-funnel/src/cde/erc1155.ts new file mode 100644 index 000000000..368ac7c14 --- /dev/null +++ b/packages/engine/paima-funnel/src/cde/erc1155.ts @@ -0,0 +1,86 @@ +import { ChainDataExtensionDatumType, DEFAULT_FUNNEL_TIMEOUT, timeout } from '@paima/utils'; +import type { + CdeErc1155TransferDatum, + ChainDataExtensionDatum, + ChainDataExtensionErc1155, +} from '@paima/sm'; +import type { + Erc1155TransferSingle as TransferSingle, + Erc1155TransferBatch as TransferBatch, +} from '@paima/utils'; + +export default async function getCdeErc1155Data( + extension: ChainDataExtensionErc1155, + fromBlock: number, + toBlock: number, + network: string +): Promise { + // TODO: typechain is missing the proper type generation for getPastEvents + // https://github.com/dethcrypto/TypeChain/issues/767 + const transferSingleEvents = (await timeout( + extension.contract.getPastEvents('TransferSingle', { + fromBlock, + toBlock, + }), + DEFAULT_FUNNEL_TIMEOUT + )) as unknown as TransferSingle[]; + const transferBatchEvents = (await timeout( + extension.contract.getPastEvents('TransferBatch', { + fromBlock, + toBlock, + }), + DEFAULT_FUNNEL_TIMEOUT + )) as unknown as TransferBatch[]; + + return [ + ...transferSingleEvents.map(e => transferSingleToDatum(e, extension, network)), + ...transferBatchEvents.map(e => transferBatchToDatum(e, extension, network)), + ]; +} + +function transferSingleToDatum( + event: TransferSingle, + extension: ChainDataExtensionErc1155, + network: string +): CdeErc1155TransferDatum { + return { + cdeId: extension.cdeId, + cdeDatumType: ChainDataExtensionDatumType.Erc1155Transfer, + blockNumber: event.blockNumber, + payload: { + operator: event.returnValues.operator, + from: event.returnValues.from, + to: event.returnValues.to, + // single->array conversion here + ids: [event.returnValues.id], + values: [event.returnValues.value], + }, + contractAddress: extension.contractAddress, + scheduledPrefix: extension.scheduledPrefix, + burnScheduledPrefix: extension.burnScheduledPrefix, + network, + }; +} + +function transferBatchToDatum( + event: TransferBatch, + extension: ChainDataExtensionErc1155, + network: string +): CdeErc1155TransferDatum { + return { + cdeId: extension.cdeId, + cdeDatumType: ChainDataExtensionDatumType.Erc1155Transfer, + blockNumber: event.blockNumber, + payload: { + operator: event.returnValues.operator, + from: event.returnValues.from, + to: event.returnValues.to, + ids: event.returnValues.ids, + values: event.returnValues.values, + }, + contractAddress: extension.contractAddress, + scheduledPrefix: extension.scheduledPrefix, + burnScheduledPrefix: extension.burnScheduledPrefix, + network, + }; +} diff --git a/packages/engine/paima-funnel/src/cde/reading.ts b/packages/engine/paima-funnel/src/cde/reading.ts index 9cdb5f80b..0f53e4b1a 100644 --- a/packages/engine/paima-funnel/src/cde/reading.ts +++ b/packages/engine/paima-funnel/src/cde/reading.ts @@ -3,14 +3,14 @@ import type Web3 from 'web3'; import { ChainDataExtensionType } from '@paima/utils'; import type { ChainDataExtensionDatum, ChainDataExtension } from '@paima/sm'; +import getCdeGenericData from './generic.js'; import getCdeErc20Data from './erc20.js'; +import getCdeErc20DepositData from './erc20Deposit.js'; import getCdeErc721Data from './erc721.js'; import getCdePaimaErc721Data from './paimaErc721.js'; -import getCdeErc20DepositData from './erc20Deposit.js'; -import getCdeGenericData from './generic.js'; import getCdeErc6551RegistryData from './erc6551Registry.js'; +import getCdeErc1155Data from './erc1155.js'; import assertNever from 'assert-never'; -import { networkInterfaces } from 'os'; export async function getUngroupedCdeData( web3: Web3, @@ -44,16 +44,18 @@ async function getSpecificCdeData( fromBlock = extension.startBlockHeight; } switch (extension.cdeType) { + case ChainDataExtensionType.Generic: + return await getCdeGenericData(extension, fromBlock, toBlock, network); case ChainDataExtensionType.ERC20: return await getCdeErc20Data(extension, fromBlock, toBlock, network); + case ChainDataExtensionType.ERC20Deposit: + return await getCdeErc20DepositData(extension, fromBlock, toBlock, network); case ChainDataExtensionType.ERC721: return await getCdeErc721Data(extension, fromBlock, toBlock, network); case ChainDataExtensionType.PaimaERC721: return await getCdePaimaErc721Data(extension, fromBlock, toBlock, network); - case ChainDataExtensionType.ERC20Deposit: - return await getCdeErc20DepositData(extension, fromBlock, toBlock, network); - case ChainDataExtensionType.Generic: - return await getCdeGenericData(extension, fromBlock, toBlock, network); + case ChainDataExtensionType.ERC1155: + return await getCdeErc1155Data(extension, fromBlock, toBlock, network); case ChainDataExtensionType.ERC6551Registry: return await getCdeErc6551RegistryData(extension, fromBlock, toBlock, network); case ChainDataExtensionType.CardanoPool: diff --git a/packages/engine/paima-runtime/src/cde-config/loading.ts b/packages/engine/paima-runtime/src/cde-config/loading.ts index 8b57345d5..e92d2b721 100644 --- a/packages/engine/paima-runtime/src/cde-config/loading.ts +++ b/packages/engine/paima-runtime/src/cde-config/loading.ts @@ -18,6 +18,7 @@ import { ERC6551_REGISTRY_DEFAULT, defaultEvmMainNetworkName, defaultCardanoNetworkName, + getErc1155Contract, } from '@paima/utils'; import type { @@ -36,6 +37,7 @@ import { ChainDataExtensionCardanoMintBurnConfig, ChainDataExtensionCardanoProjectedNFTConfig, ChainDataExtensionCardanoTransferConfig, + ChainDataExtensionErc1155Config, ChainDataExtensionErc20Config, ChainDataExtensionErc20DepositConfig, ChainDataExtensionErc6551RegistryConfig, @@ -68,7 +70,7 @@ export async function loadChainDataExtensions( ); return [instantiatedExtensions, true]; } catch (err) { - doLog(`[cde-config] Invalid config file: ${err}`); + doLog(`[cde-config] Invalid config file:`, err); return [[], false]; } } @@ -151,6 +153,15 @@ export function parseCdeConfigFile(configFileData: string): Static( ): Static { // 1) Check if there are any errors since Value.Decode doesn't give error messages { - const skippableErrors: ValueErrorType[] = [ValueErrorType.Intersect, ValueErrorType.Union]; + const lowPriorityErrors = new Set([ValueErrorType.Intersect, ValueErrorType.Union]); const errors = Array.from(Value.Errors(structure, config)); + const allErrorsLowPriority = errors.every(e => lowPriorityErrors.has(e.type)); for (const error of errors) { // there are many useless errors in this library // ex: 1st error: "foo" should be "bar" in struct Foo // 2nd error: struct Foo is invalid inside struct Config // in this case, the 2nd error is useless as we only care about the 1st error // However, we always want to show the error if for some reason it's the only error - if (errors.length !== 1 && skippableErrors.find(val => val === error.type) != null) continue; + if (!allErrorsLowPriority && lowPriorityErrors.has(error.type)) continue; console.error({ name: name ?? 'Configuration root', path: error.path, @@ -217,7 +229,7 @@ async function instantiateExtension( contract: getErc20Contract(config.contractAddress, web3s[network]), }; case CdeEntryTypeName.ERC721: - if (await isPaimaErc721(config, web3s[config.network || defaultEvmMainNetworkName])) { + if (await isPaimaErc721(config, web3s[network])) { return { ...config, network, @@ -245,6 +257,15 @@ async function instantiateExtension( cdeType: ChainDataExtensionType.ERC20Deposit, contract: getErc20Contract(config.contractAddress, web3s[network]), }; + case CdeEntryTypeName.ERC1155: + return { + ...config, + network, + cdeId: index, + hash: hashConfig(config), + cdeType: ChainDataExtensionType.ERC1155, + contract: getErc1155Contract(config.contractAddress, web3s[network]), + }; case CdeEntryTypeName.Generic: return { ...(await instantiateCdeGeneric(config, index, web3s[network])), @@ -358,7 +379,9 @@ async function instantiateCdeGeneric( eventSignatureHash, }; } catch (err) { - doLog(`[cde-config]: Fail to initialize Web3 contract with ABI ${config.abiPath}`); + doLog( + `[cde-config] Failed to initialize Web3 contract ${config.name} with ABI ${config.abiPath}` + ); throw err; } } diff --git a/packages/engine/paima-runtime/src/cde-config/utils.ts b/packages/engine/paima-runtime/src/cde-config/utils.ts index 8e0b93c31..38fa654e4 100644 --- a/packages/engine/paima-runtime/src/cde-config/utils.ts +++ b/packages/engine/paima-runtime/src/cde-config/utils.ts @@ -24,14 +24,18 @@ export function getEarliestStartSlot(config: ChainDataExtension[]): number { return isFinite(minStartSlot) ? minStartSlot : -1; } -// returns pair [rawAbiFileData, artifactObject.abi] -export async function loadAbi(abiPath: string): Promise { - let abiFileData: string = ''; +/** + * Read a contract ABI from a JSON file into an array. + * @param abiPath The JSON file path to read from. + * @returns The root if it is an array, the `abi` field if the root is an object, or `[]` on error. + */ +export async function loadAbi(abiPath: string): Promise { + let abiFileData: string; try { abiFileData = await fs.readFile(abiPath, 'utf8'); } catch (err) { doLog(`[cde-config] ABI file not found: ${abiPath}`); - return [abiFileData, []]; + return []; } try { let abiJson = JSON.parse(abiFileData); @@ -47,7 +51,7 @@ export async function loadAbi(abiPath: string): Promise { } } } catch (err) { - doLog(`[cde-config] ABI file at ${abiPath} has invalid structure`); + doLog(`[cde-config] ABI file at ${abiPath} has invalid structure`, err); } - return [abiFileData, []]; + return []; } diff --git a/packages/engine/paima-sm/src/cde-erc1155-transfer.ts b/packages/engine/paima-sm/src/cde-erc1155-transfer.ts new file mode 100644 index 000000000..a97cfeecf --- /dev/null +++ b/packages/engine/paima-sm/src/cde-erc1155-transfer.ts @@ -0,0 +1,106 @@ +import { ENV } from '@paima/utils'; +import type { CdeErc1155TransferDatum } from './types.js'; +import { + cdeErc1155ModifyBalance, + cdeErc1155DeleteIfZero, + cdeErc1155Burn, + createScheduledData, +} from '@paima/db'; +import type { + ICdeErc1155BurnParams, + ICdeErc1155DeleteIfZeroParams, + ICdeErc1155ModifyBalanceParams, + SQLUpdate, +} from '@paima/db'; + +export default async function processErc1155TransferDatum( + cdeDatum: CdeErc1155TransferDatum, + inPresync: boolean +): Promise { + const { cdeId, scheduledPrefix, burnScheduledPrefix, payload, blockNumber } = cdeDatum; + const { operator, from, to, ids, values } = payload; + const isMint = from == '0x0000000000000000000000000000000000000000'; + const isBurn = /^0x0+(dead)?$/i.test(to); + + const updateList: SQLUpdate[] = []; + + // Always schedule the plain old transfer event. + const scheduledBlockHeight = inPresync ? ENV.SM_START_BLOCKHEIGHT + 1 : blockNumber; + if (scheduledPrefix) { + const scheduledInputData = [ + scheduledPrefix, + operator, + from.toLowerCase(), + to.toLowerCase(), + JSON.stringify(ids), + JSON.stringify(values), + ].join('|'); + updateList.push(createScheduledData(scheduledInputData, scheduledBlockHeight)); + } + + if (isBurn && burnScheduledPrefix) { + const burnData = [ + burnScheduledPrefix, + operator, + from.toLowerCase(), + // to is excluded because it's presumed 0 + JSON.stringify(ids), + JSON.stringify(values), + ].join('|'); + updateList.push(createScheduledData(burnData, scheduledBlockHeight)); + } + + // Update balance + burn tables. + for (let i = 0; i < ids.length; ++i) { + let token_id = ids[i]; + let value = BigInt(values[i]); + + if (!isMint) { + // if not a mint, reduce sender's balance + updateList.push([ + cdeErc1155ModifyBalance, + { + cde_id: cdeId, + token_id, + wallet_address: from.toLowerCase(), + value: (-value).toString(), + } satisfies ICdeErc1155ModifyBalanceParams, + ]); + // And if it's zero, remove the row to keep table size down + updateList.push([ + cdeErc1155DeleteIfZero, + { + cde_id: cdeId, + token_id, + wallet_address: from.toLowerCase(), + } satisfies ICdeErc1155DeleteIfZeroParams, + ]); + } + + if (!isBurn) { + // if not a burn, increase recipient's balance + updateList.push([ + cdeErc1155ModifyBalance, + { + cde_id: cdeId, + token_id, + wallet_address: to.toLowerCase(), + value: value.toString(), + } satisfies ICdeErc1155ModifyBalanceParams, + ]); + } else { + // if a burn, increase sender's burn record + updateList.push([ + cdeErc1155Burn, + { + cde_id: cdeId, + token_id, + wallet_address: from.toLowerCase(), + value: value.toString(), + } satisfies ICdeErc1155BurnParams, + ]); + } + } + + return updateList; +} diff --git a/packages/engine/paima-sm/src/cde-processing.ts b/packages/engine/paima-sm/src/cde-processing.ts index 49713ae77..dcce614ae 100644 --- a/packages/engine/paima-sm/src/cde-processing.ts +++ b/packages/engine/paima-sm/src/cde-processing.ts @@ -8,6 +8,7 @@ import processErc721TransferDatum from './cde-erc721-transfer.js'; import processErc721MintDatum from './cde-erc721-mint.js'; import processErc20DepositDatum from './cde-erc20-deposit.js'; import processErc6551RegistryDatum from './cde-erc6551-registry.js'; +import processErc1155TransferDatum from './cde-erc1155-transfer.js'; import processGenericDatum from './cde-generic.js'; import processCardanoDelegationDatum from './cde-cardano-pool.js'; import processCardanoProjectedNFT from './cde-cardano-projected-nft.js'; @@ -31,6 +32,8 @@ export async function cdeTransitionFunction( return await processErc721MintDatum(cdeDatum, inPresync); case ChainDataExtensionDatumType.ERC20Deposit: return await processErc20DepositDatum(readonlyDBConn, cdeDatum, inPresync); + case ChainDataExtensionDatumType.Erc1155Transfer: + return await processErc1155TransferDatum(cdeDatum, inPresync); case ChainDataExtensionDatumType.Generic: return await processGenericDatum(cdeDatum, inPresync); case ChainDataExtensionDatumType.ERC6551Registry: diff --git a/packages/engine/paima-sm/src/types.ts b/packages/engine/paima-sm/src/types.ts index 664d5dea6..7ba427681 100644 --- a/packages/engine/paima-sm/src/types.ts +++ b/packages/engine/paima-sm/src/types.ts @@ -15,6 +15,7 @@ import type { InternalEventType, ConfigNetworkType, STFSubmittedData, + IERC1155Contract, } from '@paima/utils'; import { Type } from '@sinclair/typebox'; import type { Static } from '@sinclair/typebox'; @@ -80,6 +81,14 @@ interface CdeDatumErc20DepositPayload { value: string; } +interface CdeDatumErc1155TransferPayload { + operator: string; // address + from: string; // address + to: string; // address + ids: string[]; // uint256, might have just one entry + values: string[]; // uint256, might have just one entry +} + type CdeDatumGenericPayload = any; interface CdeDatumErc6551RegistryPayload { @@ -185,6 +194,14 @@ export interface CdeErc20DepositDatum extends CdeDatumBase { scheduledPrefix: string; } +export interface CdeErc1155TransferDatum extends CdeDatumBase { + cdeDatumType: ChainDataExtensionDatumType.Erc1155Transfer; + payload: CdeDatumErc1155TransferPayload; + contractAddress: string; + scheduledPrefix?: string | undefined; + burnScheduledPrefix?: string | undefined; +} + export interface CdeGenericDatum extends CdeDatumBase { cdeDatumType: ChainDataExtensionDatumType.Generic; payload: CdeDatumGenericPayload; @@ -235,6 +252,7 @@ export type ChainDataExtensionDatum = | CdeErc721MintDatum | CdeErc721TransferDatum | CdeErc20DepositDatum + | CdeErc1155TransferDatum | CdeGenericDatum | CdeErc6551RegistryDatum | CdeCardanoPoolDatum @@ -249,6 +267,7 @@ export enum CdeEntryTypeName { ERC20Deposit = 'erc20-deposit', ERC721 = 'erc721', ERC6551Registry = 'erc6551-registry', + ERC1155 = 'erc1155', CardanoDelegation = 'cardano-stake-delegation', CardanoProjectedNFT = 'cardano-projected-nft', CardanoDelayedAsset = 'cardano-delayed-asset', @@ -321,6 +340,21 @@ export type ChainDataExtensionErc20Deposit = ChainDataExtensionBase & contract: ERC20Contract; }; +export const ChainDataExtensionErc1155Config = Type.Intersect([ + ChainDataExtensionConfigBase, + Type.Object({ + type: Type.Literal(CdeEntryTypeName.ERC1155), + contractAddress: EvmAddress, + scheduledPrefix: Type.Optional(Type.String()), + burnScheduledPrefix: Type.Optional(Type.String()), + }), +]); +export type ChainDataExtensionErc1155 = ChainDataExtensionBase & + Static & { + cdeType: ChainDataExtensionType.ERC1155; + contract: IERC1155Contract; + }; + export const ChainDataExtensionGenericConfig = Type.Intersect([ ChainDataExtensionConfigBase, Type.Object({ @@ -433,10 +467,11 @@ export const CdeConfig = Type.Object({ Type.Intersect([ Type.Union([ ChainDataExtensionErc20Config, - ChainDataExtensionErc721Config, ChainDataExtensionErc20DepositConfig, - ChainDataExtensionGenericConfig, + ChainDataExtensionErc721Config, + ChainDataExtensionErc1155Config, ChainDataExtensionErc6551RegistryConfig, + ChainDataExtensionGenericConfig, ChainDataExtensionCardanoDelegationConfig, ChainDataExtensionCardanoProjectedNFTConfig, ChainDataExtensionCardanoDelayedAssetConfig, @@ -463,11 +498,12 @@ export const CdeBaseConfig = Type.Object({ }); export type ChainDataExtension = ( | ChainDataExtensionErc20 + | ChainDataExtensionErc20Deposit | ChainDataExtensionErc721 | ChainDataExtensionPaimaErc721 - | ChainDataExtensionErc20Deposit - | ChainDataExtensionGeneric + | ChainDataExtensionErc1155 | ChainDataExtensionErc6551Registry + | ChainDataExtensionGeneric | ChainDataExtensionCardanoDelegation | ChainDataExtensionCardanoProjectedNFT | ChainDataExtensionCardanoDelayedAsset diff --git a/packages/node-sdk/paima-db/migrations/up.sql b/packages/node-sdk/paima-db/migrations/up.sql index 45435834c..3bfc12861 100644 --- a/packages/node-sdk/paima-db/migrations/up.sql +++ b/packages/node-sdk/paima-db/migrations/up.sql @@ -63,6 +63,22 @@ CREATE TABLE cde_erc721_burn ( PRIMARY KEY(cde_id, token_id) ); +CREATE TABLE cde_erc1155_data ( + cde_id INTEGER NOT NULL, + token_id TEXT NOT NULL, + wallet_address TEXT NOT NULL, + balance TEXT NOT NULL, + PRIMARY KEY (cde_id, token_id, wallet_address) +); + +CREATE TABLE cde_erc1155_burn ( + cde_id INTEGER NOT NULL, + token_id TEXT NOT NULL, + wallet_address TEXT NOT NULL, + balance TEXT NOT NULL, + PRIMARY KEY (cde_id, token_id, wallet_address) +); + CREATE TABLE cde_erc20_deposit_data ( cde_id INTEGER NOT NULL, wallet_address TEXT NOT NULL, @@ -224,4 +240,4 @@ CREATE TABLE cde_cardano_mint_burn( input_addresses JSONB NOT NULL, output_addresses JSONB NOT NULL, PRIMARY KEY (cde_id, tx_id) -); \ No newline at end of file +); diff --git a/packages/node-sdk/paima-db/src/index.ts b/packages/node-sdk/paima-db/src/index.ts index d4604ed32..13a0639fa 100644 --- a/packages/node-sdk/paima-db/src/index.ts +++ b/packages/node-sdk/paima-db/src/index.ts @@ -26,6 +26,8 @@ export * from './sql/cde-erc20-deposit.queries.js'; export type * from './sql/cde-erc20-deposit.queries.js'; export * from './sql/cde-generic.queries.js'; export type * from './sql/cde-generic.queries.js'; +export * from './sql/cde-erc1155.queries.js'; +export type * from './sql/cde-erc1155.queries.js'; export * from './sql/cde-erc6551-registry.queries.js'; export type * from './sql/cde-erc6551-registry.queries.js'; export * from './sql/emulated.queries.js'; diff --git a/packages/node-sdk/paima-db/src/paima-tables.ts b/packages/node-sdk/paima-db/src/paima-tables.ts index 8fffb9865..6566161b9 100644 --- a/packages/node-sdk/paima-db/src/paima-tables.ts +++ b/packages/node-sdk/paima-db/src/paima-tables.ts @@ -227,6 +227,52 @@ const TABLE_DATA_CDE_ERC721_BURN: TableData = { creationQuery: QUERY_CREATE_TABLE_CDE_ERC721_BURN, }; +const QUERY_CREATE_TABLE_CDE_ERC1155_DATA = ` +CREATE TABLE cde_erc1155_data ( + cde_id INTEGER NOT NULL, + token_id TEXT NOT NULL, + wallet_address TEXT NOT NULL, + balance TEXT NOT NULL, + PRIMARY KEY (cde_id, token_id, wallet_address) +); +`; + +const TABLE_DATA_CDE_ERC1155_DATA: TableData = { + tableName: 'cde_erc1155_data', + primaryKeyColumns: ['cde_id', 'token_id'], + columnData: packTuples([ + ['cde_id', 'integer', 'NO', ''], + ['token_id', 'text', 'NO', ''], + ['wallet_address', 'text', 'NO', ''], + ['balance', 'text', 'NO', ''], + ]), + serialColumns: [], + creationQuery: QUERY_CREATE_TABLE_CDE_ERC1155_DATA, +}; + +const QUERY_CREATE_TABLE_CDE_ERC1155_BURN = ` +CREATE TABLE cde_erc1155_burn ( + cde_id INTEGER NOT NULL, + token_id TEXT NOT NULL, + wallet_address TEXT NOT NULL, + balance TEXT NOT NULL, + PRIMARY KEY (cde_id, token_id, wallet_address) +); +`; + +const TABLE_DATA_CDE_ERC1155_BURN: TableData = { + tableName: 'cde_erc1155_burn', + primaryKeyColumns: ['cde_id', 'token_id'], + columnData: packTuples([ + ['cde_id', 'integer', 'NO', ''], + ['token_id', 'text', 'NO', ''], + ['wallet_address', 'text', 'NO', ''], + ['balance', 'text', 'NO', ''], + ]), + serialColumns: [], + creationQuery: QUERY_CREATE_TABLE_CDE_ERC1155_BURN, +}; + const QUERY_CREATE_TABLE_CDE_ERC20_DEPOSIT = ` CREATE TABLE cde_erc20_deposit_data ( cde_id INTEGER NOT NULL, @@ -602,6 +648,8 @@ export const TABLES: TableData[] = [ TABLE_DATA_CDE_ERC20, TABLE_DATA_CDE_ERC721, TABLE_DATA_CDE_ERC721_BURN, + TABLE_DATA_CDE_ERC1155_DATA, + TABLE_DATA_CDE_ERC1155_BURN, TABLE_DATA_CDE_ERC20_DEPOSIT, TABLE_DATA_CDE_GENERIC_DATA, TABLE_DATA_CDE_ERC6551_REGISTRY, diff --git a/packages/node-sdk/paima-db/src/sql/cde-erc1155.queries.ts b/packages/node-sdk/paima-db/src/sql/cde-erc1155.queries.ts new file mode 100644 index 000000000..c789395ad --- /dev/null +++ b/packages/node-sdk/paima-db/src/sql/cde-erc1155.queries.ts @@ -0,0 +1,218 @@ +/** Types generated for queries found in "src/sql/cde-erc1155.sql" */ +import { PreparedQuery } from '@pgtyped/runtime'; + +/** 'CdeErc1155ModifyBalance' parameters type */ +export interface ICdeErc1155ModifyBalanceParams { + cde_id: number; + token_id: string; + value: string; + wallet_address: string; +} + +/** 'CdeErc1155ModifyBalance' return type */ +export type ICdeErc1155ModifyBalanceResult = void; + +/** 'CdeErc1155ModifyBalance' query type */ +export interface ICdeErc1155ModifyBalanceQuery { + params: ICdeErc1155ModifyBalanceParams; + result: ICdeErc1155ModifyBalanceResult; +} + +const cdeErc1155ModifyBalanceIR: any = {"usedParamSet":{"cde_id":true,"token_id":true,"wallet_address":true,"value":true},"params":[{"name":"cde_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":94,"b":101}]},{"name":"token_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":106,"b":115}]},{"name":"wallet_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":120,"b":135}]},{"name":"value","required":true,"transform":{"type":"scalar"},"locs":[{"a":140,"b":146}]}],"statement":"INSERT INTO cde_erc1155_data (\n cde_id,\n token_id,\n wallet_address,\n balance\n)\nVALUES (\n :cde_id!,\n :token_id!,\n :wallet_address!,\n :value!\n)\nON CONFLICT (cde_id, token_id, wallet_address)\nDO UPDATE SET balance = CAST(cde_erc1155_data.balance AS NUMERIC) + CAST(EXCLUDED.balance AS NUMERIC)"}; + +/** + * Query generated from SQL: + * ``` + * INSERT INTO cde_erc1155_data ( + * cde_id, + * token_id, + * wallet_address, + * balance + * ) + * VALUES ( + * :cde_id!, + * :token_id!, + * :wallet_address!, + * :value! + * ) + * ON CONFLICT (cde_id, token_id, wallet_address) + * DO UPDATE SET balance = CAST(cde_erc1155_data.balance AS NUMERIC) + CAST(EXCLUDED.balance AS NUMERIC) + * ``` + */ +export const cdeErc1155ModifyBalance = new PreparedQuery(cdeErc1155ModifyBalanceIR); + + +/** 'CdeErc1155DeleteIfZero' parameters type */ +export interface ICdeErc1155DeleteIfZeroParams { + cde_id: number; + token_id: string; + wallet_address: string; +} + +/** 'CdeErc1155DeleteIfZero' return type */ +export type ICdeErc1155DeleteIfZeroResult = void; + +/** 'CdeErc1155DeleteIfZero' query type */ +export interface ICdeErc1155DeleteIfZeroQuery { + params: ICdeErc1155DeleteIfZeroParams; + result: ICdeErc1155DeleteIfZeroResult; +} + +const cdeErc1155DeleteIfZeroIR: any = {"usedParamSet":{"cde_id":true,"token_id":true,"wallet_address":true},"params":[{"name":"cde_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":62,"b":69}]},{"name":"token_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":86,"b":95}]},{"name":"wallet_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":118,"b":133}]}],"statement":"DELETE FROM cde_erc1155_data\nWHERE balance = '0'\nAND cde_id = :cde_id!\nAND token_id = :token_id!\nAND wallet_address = :wallet_address!"}; + +/** + * Query generated from SQL: + * ``` + * DELETE FROM cde_erc1155_data + * WHERE balance = '0' + * AND cde_id = :cde_id! + * AND token_id = :token_id! + * AND wallet_address = :wallet_address! + * ``` + */ +export const cdeErc1155DeleteIfZero = new PreparedQuery(cdeErc1155DeleteIfZeroIR); + + +/** 'CdeErc1155Burn' parameters type */ +export interface ICdeErc1155BurnParams { + cde_id: number; + token_id: string; + value: string; + wallet_address: string; +} + +/** 'CdeErc1155Burn' return type */ +export type ICdeErc1155BurnResult = void; + +/** 'CdeErc1155Burn' query type */ +export interface ICdeErc1155BurnQuery { + params: ICdeErc1155BurnParams; + result: ICdeErc1155BurnResult; +} + +const cdeErc1155BurnIR: any = {"usedParamSet":{"cde_id":true,"token_id":true,"wallet_address":true,"value":true},"params":[{"name":"cde_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":94,"b":101}]},{"name":"token_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":106,"b":115}]},{"name":"wallet_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":120,"b":135}]},{"name":"value","required":true,"transform":{"type":"scalar"},"locs":[{"a":140,"b":146}]}],"statement":"INSERT INTO cde_erc1155_burn (\n cde_id,\n token_id,\n wallet_address,\n balance\n)\nVALUES (\n :cde_id!,\n :token_id!,\n :wallet_address!,\n :value!\n)\nON CONFLICT (cde_id, token_id, wallet_address)\nDO UPDATE SET balance = CAST(cde_erc1155_burn.balance AS NUMERIC) + CAST(EXCLUDED.balance AS NUMERIC)"}; + +/** + * Query generated from SQL: + * ``` + * INSERT INTO cde_erc1155_burn ( + * cde_id, + * token_id, + * wallet_address, + * balance + * ) + * VALUES ( + * :cde_id!, + * :token_id!, + * :wallet_address!, + * :value! + * ) + * ON CONFLICT (cde_id, token_id, wallet_address) + * DO UPDATE SET balance = CAST(cde_erc1155_burn.balance AS NUMERIC) + CAST(EXCLUDED.balance AS NUMERIC) + * ``` + */ +export const cdeErc1155Burn = new PreparedQuery(cdeErc1155BurnIR); + + +/** 'CdeErc1155GetAllTokens' parameters type */ +export interface ICdeErc1155GetAllTokensParams { + cde_id: number; + wallet_address: string; +} + +/** 'CdeErc1155GetAllTokens' return type */ +export interface ICdeErc1155GetAllTokensResult { + balance: string; + cde_id: number; + token_id: string; + wallet_address: string; +} + +/** 'CdeErc1155GetAllTokens' query type */ +export interface ICdeErc1155GetAllTokensQuery { + params: ICdeErc1155GetAllTokensParams; + result: ICdeErc1155GetAllTokensResult; +} + +const cdeErc1155GetAllTokensIR: any = {"usedParamSet":{"cde_id":true,"wallet_address":true},"params":[{"name":"cde_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":46,"b":53}]},{"name":"wallet_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":76,"b":91}]}],"statement":"SELECT * from cde_erc1155_data\nWHERE cde_id = :cde_id!\nAND wallet_address = :wallet_address!\nAND CAST(balance AS NUMERIC) > 0"}; + +/** + * Query generated from SQL: + * ``` + * SELECT * from cde_erc1155_data + * WHERE cde_id = :cde_id! + * AND wallet_address = :wallet_address! + * AND CAST(balance AS NUMERIC) > 0 + * ``` + */ +export const cdeErc1155GetAllTokens = new PreparedQuery(cdeErc1155GetAllTokensIR); + + +/** 'CdeErc1155GetByTokenId' parameters type */ +export interface ICdeErc1155GetByTokenIdParams { + cde_id: number; + token_id: string; +} + +/** 'CdeErc1155GetByTokenId' return type */ +export interface ICdeErc1155GetByTokenIdResult { + balance: string; + cde_id: number; + token_id: string; + wallet_address: string; +} + +/** 'CdeErc1155GetByTokenId' query type */ +export interface ICdeErc1155GetByTokenIdQuery { + params: ICdeErc1155GetByTokenIdParams; + result: ICdeErc1155GetByTokenIdResult; +} + +const cdeErc1155GetByTokenIdIR: any = {"usedParamSet":{"cde_id":true,"token_id":true},"params":[{"name":"cde_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":46,"b":53}]},{"name":"token_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":70,"b":79}]}],"statement":"SELECT * from cde_erc1155_data\nWHERE cde_id = :cde_id!\nAND token_id = :token_id!"}; + +/** + * Query generated from SQL: + * ``` + * SELECT * from cde_erc1155_data + * WHERE cde_id = :cde_id! + * AND token_id = :token_id! + * ``` + */ +export const cdeErc1155GetByTokenId = new PreparedQuery(cdeErc1155GetByTokenIdIR); + + +/** 'CdeErc1155GetByTokenIdAndWallet' parameters type */ +export interface ICdeErc1155GetByTokenIdAndWalletParams { + cde_id: number; + token_id: string; + wallet_address: string; +} + +/** 'CdeErc1155GetByTokenIdAndWallet' return type */ +export interface ICdeErc1155GetByTokenIdAndWalletResult { + balance: string; + cde_id: number; + token_id: string; + wallet_address: string; +} + +/** 'CdeErc1155GetByTokenIdAndWallet' query type */ +export interface ICdeErc1155GetByTokenIdAndWalletQuery { + params: ICdeErc1155GetByTokenIdAndWalletParams; + result: ICdeErc1155GetByTokenIdAndWalletResult; +} + +const cdeErc1155GetByTokenIdAndWalletIR: any = {"usedParamSet":{"cde_id":true,"wallet_address":true,"token_id":true},"params":[{"name":"cde_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":46,"b":53}]},{"name":"wallet_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":76,"b":91}]},{"name":"token_id","required":true,"transform":{"type":"scalar"},"locs":[{"a":108,"b":117}]}],"statement":"SELECT * from cde_erc1155_data\nWHERE cde_id = :cde_id!\nAND wallet_address = :wallet_address!\nAND token_id = :token_id!"}; + +/** + * Query generated from SQL: + * ``` + * SELECT * from cde_erc1155_data + * WHERE cde_id = :cde_id! + * AND wallet_address = :wallet_address! + * AND token_id = :token_id! + * ``` + */ +export const cdeErc1155GetByTokenIdAndWallet = new PreparedQuery(cdeErc1155GetByTokenIdAndWalletIR); + + diff --git a/packages/node-sdk/paima-db/src/sql/cde-erc1155.sql b/packages/node-sdk/paima-db/src/sql/cde-erc1155.sql new file mode 100644 index 000000000..cc64e0f47 --- /dev/null +++ b/packages/node-sdk/paima-db/src/sql/cde-erc1155.sql @@ -0,0 +1,58 @@ +/* @name cdeErc1155ModifyBalance */ +INSERT INTO cde_erc1155_data ( + cde_id, + token_id, + wallet_address, + balance +) +VALUES ( + :cde_id!, + :token_id!, + :wallet_address!, + :value! +) +ON CONFLICT (cde_id, token_id, wallet_address) +DO UPDATE SET balance = CAST(cde_erc1155_data.balance AS NUMERIC) + CAST(EXCLUDED.balance AS NUMERIC); + +/* @name cdeErc1155DeleteIfZero */ +DELETE FROM cde_erc1155_data +WHERE balance = '0' +AND cde_id = :cde_id! +AND token_id = :token_id! +AND wallet_address = :wallet_address!; + +/* @name cdeErc1155Burn */ +INSERT INTO cde_erc1155_burn ( + cde_id, + token_id, + wallet_address, + balance +) +VALUES ( + :cde_id!, + :token_id!, + :wallet_address!, + :value! +) +ON CONFLICT (cde_id, token_id, wallet_address) +DO UPDATE SET balance = CAST(cde_erc1155_burn.balance AS NUMERIC) + CAST(EXCLUDED.balance AS NUMERIC); + +/* @name cdeErc1155GetAllTokens */ +SELECT * from cde_erc1155_data +WHERE cde_id = :cde_id! +AND wallet_address = :wallet_address! +AND CAST(balance AS NUMERIC) > 0 +; + +/* @name cdeErc1155GetByTokenId */ +SELECT * from cde_erc1155_data +WHERE cde_id = :cde_id! +AND token_id = :token_id! +; + +/* @name cdeErc1155GetByTokenIdAndWallet */ +SELECT * from cde_erc1155_data +WHERE cde_id = :cde_id! +AND wallet_address = :wallet_address! +AND token_id = :token_id! +; diff --git a/packages/node-sdk/paima-utils-backend/src/cde-access-internals.ts b/packages/node-sdk/paima-utils-backend/src/cde-access-internals.ts index 86b4fc00a..8cd3ac78c 100644 --- a/packages/node-sdk/paima-utils-backend/src/cde-access-internals.ts +++ b/packages/node-sdk/paima-utils-backend/src/cde-access-internals.ts @@ -17,6 +17,9 @@ import { type ICdeCardanoGetProjectedNftResult, getCardanoEpoch, cdeCardanoAssetUtxosByAddress, + cdeErc1155GetAllTokens, + cdeErc1155GetByTokenId, + cdeErc1155GetByTokenIdAndWallet, } from '@paima/db'; import type { OwnedNftsResponse, @@ -24,7 +27,12 @@ import type { TokenIdPair, CardanoAssetUtxo, } from './types.js'; -import type { ICdeCardanoAssetUtxosByAddressParams } from '@paima/db'; +import type { + ICdeCardanoAssetUtxosByAddressParams, + ICdeErc1155GetAllTokensResult, + ICdeErc1155GetByTokenIdAndWalletResult, + ICdeErc1155GetByTokenIdResult, +} from '@paima/db'; /* Functions to retrieve CDE ID: */ @@ -158,6 +166,38 @@ export async function internalGetGenericDataBlockheightRange( })); } +export async function internalGetErc1155AllTokens( + readonlyDBConn: Pool, + cde_id: number, + wallet_address: string +): Promise { + return await cdeErc1155GetAllTokens.run({ cde_id, wallet_address }, readonlyDBConn); +} + +export async function internalGetErc1155ByTokenId( + readonlyDBConn: Pool, + cde_id: number, + token_id: bigint +): Promise { + return ( + await cdeErc1155GetByTokenId.run({ cde_id, token_id: String(token_id) }, readonlyDBConn) + )[0]; +} + +export async function internalGetErc1155ByTokenIdAndWallet( + readonlyDBConn: Pool, + cde_id: number, + wallet_address: string, + token_id: bigint +): Promise { + return ( + await cdeErc1155GetByTokenIdAndWallet.run( + { cde_id, wallet_address, token_id: String(token_id) }, + readonlyDBConn + ) + )[0]; +} + export async function internalGetErc6551AccountOwner( readonlyDBConn: Pool, cdeId: number, diff --git a/packages/node-sdk/paima-utils-backend/src/cde-access.ts b/packages/node-sdk/paima-utils-backend/src/cde-access.ts index 85d7df4d0..f0fe6760b 100644 --- a/packages/node-sdk/paima-utils-backend/src/cde-access.ts +++ b/packages/node-sdk/paima-utils-backend/src/cde-access.ts @@ -15,8 +15,17 @@ import { internalGetCardanoAddressDelegation, internalGetCardanoProjectedNft, internalGetCardanoAssetUtxos, + internalGetErc1155AllTokens, + internalGetErc1155ByTokenId, + internalGetErc1155ByTokenIdAndWallet, } from './cde-access-internals.js'; -import type { ICdeCardanoGetProjectedNftResult } from '@paima/db/src'; +import type { + ICdeCardanoGetProjectedNftResult, + ICdeErc1155GetAllTokensResult, + ICdeErc1155GetByTokenIdAndWalletResult, + ICdeErc1155GetByTokenIdResult, +} from '@paima/db'; +export type { ICdeErc1155GetAllTokensResult }; import type { OwnedNftsResponse, GenericCdeDataUnit, @@ -140,6 +149,46 @@ export async function getGenericDataBlockheightRange( return await internalGetGenericDataBlockheightRange(readonlyDBConn, cdeId, fromBlock, toBlock); } +/** + * Get a listing of all tokens owned by a wallet within a single ERC-1155 contract. + */ +export async function getErc1155AllTokens( + readonlyDBConn: Pool, + cdeName: string, + wallet: string +): Promise { + const cdeId = await getCdeIdByName(readonlyDBConn, cdeName); + if (cdeId === null) return []; + return await internalGetErc1155AllTokens(readonlyDBConn, cdeId, wallet); +} + +/** + * Get info on a specific token within a single ERC-1155 contract. + */ +export async function getErc1155ByTokenId( + readonlyDBConn: Pool, + cdeName: string, + tokenId: bigint +): Promise { + const cdeId = await getCdeIdByName(readonlyDBConn, cdeName); + if (cdeId === null) return null; + return await internalGetErc1155ByTokenId(readonlyDBConn, cdeId, tokenId); +} + +/** + * Get info on a specific token owned by a wallet within a single ERC-1155 contract. + */ +export async function getErc1155ByTokenIdAndWallet( + readonlyDBConn: Pool, + cdeName: string, + wallet: string, + tokenId: bigint +): Promise { + const cdeId = await getCdeIdByName(readonlyDBConn, cdeName); + if (cdeId === null) return null; + return await internalGetErc1155ByTokenIdAndWallet(readonlyDBConn, cdeId, wallet, tokenId); +} + /** * Fetch the NFT that owns this account */ diff --git a/packages/paima-sdk/paima-utils/src/artifacts/IERC1155Contract.json b/packages/paima-sdk/paima-utils/src/artifacts/IERC1155Contract.json new file mode 100644 index 000000000..bb8598ac7 --- /dev/null +++ b/packages/paima-sdk/paima-utils/src/artifacts/IERC1155Contract.json @@ -0,0 +1,297 @@ +{ + "abi": [ + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "balanceOfBatch", + "inputs": [ + { + "name": "accounts", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "ids", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isApprovedForAll", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "operator", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "safeBatchTransferFrom", + "inputs": [ + { + "name": "from", + "type": "address", + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "ids", + "type": "uint256[]", + "internalType": "uint256[]" + }, + { + "name": "values", + "type": "uint256[]", + "internalType": "uint256[]" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "safeTransferFrom", + "inputs": [ + { + "name": "from", + "type": "address", + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setApprovalForAll", + "inputs": [ + { + "name": "operator", + "type": "address", + "internalType": "address" + }, + { + "name": "approved", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ApprovalForAll", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "operator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "approved", + "type": "bool", + "indexed": false, + "internalType": "bool" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TransferBatch", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "ids", + "type": "uint256[]", + "indexed": false, + "internalType": "uint256[]" + }, + { + "name": "values", + "type": "uint256[]", + "indexed": false, + "internalType": "uint256[]" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TransferSingle", + "inputs": [ + { + "name": "operator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "id", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "URI", + "inputs": [ + { + "name": "value", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + } + ], + "anonymous": false + } + ] +} diff --git a/packages/paima-sdk/paima-utils/src/artifacts/IERC1155Contract.ts b/packages/paima-sdk/paima-utils/src/artifacts/IERC1155Contract.ts new file mode 100644 index 000000000..bdfb3ac67 --- /dev/null +++ b/packages/paima-sdk/paima-utils/src/artifacts/IERC1155Contract.ts @@ -0,0 +1,297 @@ +export default { + abi: [ + { + type: 'function', + name: 'balanceOf', + inputs: [ + { + name: 'account', + type: 'address', + internalType: 'address', + }, + { + name: 'id', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'balanceOfBatch', + inputs: [ + { + name: 'accounts', + type: 'address[]', + internalType: 'address[]', + }, + { + name: 'ids', + type: 'uint256[]', + internalType: 'uint256[]', + }, + ], + outputs: [ + { + name: '', + type: 'uint256[]', + internalType: 'uint256[]', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'isApprovedForAll', + inputs: [ + { + name: 'account', + type: 'address', + internalType: 'address', + }, + { + name: 'operator', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'bool', + internalType: 'bool', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'safeBatchTransferFrom', + inputs: [ + { + name: 'from', + type: 'address', + internalType: 'address', + }, + { + name: 'to', + type: 'address', + internalType: 'address', + }, + { + name: 'ids', + type: 'uint256[]', + internalType: 'uint256[]', + }, + { + name: 'values', + type: 'uint256[]', + internalType: 'uint256[]', + }, + { + name: 'data', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'safeTransferFrom', + inputs: [ + { + name: 'from', + type: 'address', + internalType: 'address', + }, + { + name: 'to', + type: 'address', + internalType: 'address', + }, + { + name: 'id', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'value', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'data', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'setApprovalForAll', + inputs: [ + { + name: 'operator', + type: 'address', + internalType: 'address', + }, + { + name: 'approved', + type: 'bool', + internalType: 'bool', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'supportsInterface', + inputs: [ + { + name: 'interfaceId', + type: 'bytes4', + internalType: 'bytes4', + }, + ], + outputs: [ + { + name: '', + type: 'bool', + internalType: 'bool', + }, + ], + stateMutability: 'view', + }, + { + type: 'event', + name: 'ApprovalForAll', + inputs: [ + { + name: 'account', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'operator', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'approved', + type: 'bool', + indexed: false, + internalType: 'bool', + }, + ], + anonymous: false, + }, + { + type: 'event', + name: 'TransferBatch', + inputs: [ + { + name: 'operator', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'from', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'to', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'ids', + type: 'uint256[]', + indexed: false, + internalType: 'uint256[]', + }, + { + name: 'values', + type: 'uint256[]', + indexed: false, + internalType: 'uint256[]', + }, + ], + anonymous: false, + }, + { + type: 'event', + name: 'TransferSingle', + inputs: [ + { + name: 'operator', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'from', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'to', + type: 'address', + indexed: true, + internalType: 'address', + }, + { + name: 'id', + type: 'uint256', + indexed: false, + internalType: 'uint256', + }, + { + name: 'value', + type: 'uint256', + indexed: false, + internalType: 'uint256', + }, + ], + anonymous: false, + }, + { + type: 'event', + name: 'URI', + inputs: [ + { + name: 'value', + type: 'string', + indexed: false, + internalType: 'string', + }, + { + name: 'id', + type: 'uint256', + indexed: true, + internalType: 'uint256', + }, + ], + anonymous: false, + }, + ], +}; diff --git a/packages/paima-sdk/paima-utils/src/config/loading.ts b/packages/paima-sdk/paima-utils/src/config/loading.ts index 8b4d01e3f..34bd8cb0e 100644 --- a/packages/paima-sdk/paima-utils/src/config/loading.ts +++ b/packages/paima-sdk/paima-utils/src/config/loading.ts @@ -177,7 +177,7 @@ export async function loadConfig(): Promise