@trufnetwork/sdk-js 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client/client.cjs +11 -0
- package/dist/cjs/client/client.cjs.map +2 -2
- package/dist/cjs/client/getLastTransactions.cjs +39 -18
- package/dist/cjs/client/getLastTransactions.cjs.map +2 -2
- package/dist/cjs/contracts-api/action.cjs +3 -1
- package/dist/cjs/contracts-api/action.cjs.map +2 -2
- package/dist/cjs/contracts-api/attestationAction.cjs +9 -4
- package/dist/cjs/contracts-api/attestationAction.cjs.map +2 -2
- package/dist/cjs/contracts-api/transactionAction.cjs +139 -0
- package/dist/cjs/contracts-api/transactionAction.cjs.map +7 -0
- package/dist/cjs/types/attestation.cjs +2 -1
- package/dist/cjs/types/attestation.cjs.map +2 -2
- package/dist/cjs/types/transaction.cjs.map +1 -1
- package/dist/esm/client/client.mjs +11 -0
- package/dist/esm/client/client.mjs.map +2 -2
- package/dist/esm/client/getLastTransactions.mjs +39 -18
- package/dist/esm/client/getLastTransactions.mjs.map +2 -2
- package/dist/esm/contracts-api/action.mjs +3 -1
- package/dist/esm/contracts-api/action.mjs.map +2 -2
- package/dist/esm/contracts-api/attestationAction.mjs +9 -4
- package/dist/esm/contracts-api/attestationAction.mjs.map +2 -2
- package/dist/esm/contracts-api/transactionAction.mjs +122 -0
- package/dist/esm/contracts-api/transactionAction.mjs.map +7 -0
- package/dist/esm/types/attestation.mjs +2 -1
- package/dist/esm/types/attestation.mjs.map +2 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/client/client.d.ts +6 -0
- package/dist/types/client/client.d.ts.map +1 -1
- package/dist/types/client/getLastTransactions.d.ts.map +1 -1
- package/dist/types/contracts-api/action.d.ts +2 -1
- package/dist/types/contracts-api/action.d.ts.map +1 -1
- package/dist/types/contracts-api/attestationAction.d.ts.map +1 -1
- package/dist/types/contracts-api/transactionAction.d.ts +36 -0
- package/dist/types/contracts-api/transactionAction.d.ts.map +1 -0
- package/dist/types/types/attestation.d.ts +4 -2
- package/dist/types/types/attestation.d.ts.map +1 -1
- package/dist/types/types/transaction.d.ts +59 -0
- package/dist/types/types/transaction.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/contracts-api/attestationAction.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Attestation action implementation\n *\n * This module provides methods for requesting, retrieving, and listing attestations.\n * Attestations are cryptographically signed proofs of query results that can be\n * consumed by smart contracts and external applications.\n */\n\nimport { Types } from '@trufnetwork/kwil-js';\nimport { Action } from './action';\nimport {\n RequestAttestationInput,\n RequestAttestationResult,\n GetSignedAttestationInput,\n SignedAttestationResult,\n ListAttestationsInput,\n AttestationMetadata,\n validateAttestationRequest,\n validateListAttestationsInput,\n} from '../types/attestation';\nimport { encodeActionArgs } from '../util/AttestationEncoding';\n\n/**\n * AttestationAction provides methods for working with data attestations\n *\n * Attestations enable validators to cryptographically sign query results,\n * providing verifiable proofs that can be used in smart contracts.\n *\n * @example\n * ```typescript\n * const client = new NodeTNClient({ ... });\n * const attestationAction = client.loadAttestationAction();\n *\n * // Request an attestation\n * const result = await attestationAction.requestAttestation({\n * dataProvider: \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\",\n * streamId: \"stai0000000000000000000000000000\",\n * actionName: \"get_record\",\n * args: [dataProvider, streamId, fromTime, toTime, null, false],\n * encryptSig: false,\n * maxFee: 1000000,\n * });\n *\n * // Wait for signing (1-2 blocks)\n * await new Promise(resolve => setTimeout(resolve, 10000));\n *\n * // Retrieve signed attestation\n * const signed = await attestationAction.getSignedAttestation({\n * requestTxId: result.requestTxId,\n * });\n * ```\n */\nexport class AttestationAction extends Action {\n /**\n * Request a signed attestation of query results\n *\n * This submits a transaction requesting that validators execute a query\n * and sign the results. The leader validator will sign the attestation\n * asynchronously (typically 1-2 blocks later).\n *\n * @param input - Attestation request parameters\n * @returns Promise resolving to request result with transaction ID\n * @throws Error if validation fails or transaction fails\n *\n * @example\n * ```typescript\n * const result = await attestationAction.requestAttestation({\n * dataProvider: \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\",\n * streamId: \"stai0000000000000000000000000000\",\n * actionName: \"get_record\",\n * args: [\n * \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\",\n * \"stai0000000000000000000000000000\",\n * Math.floor(Date.now() / 1000) - 86400, // 1 day ago\n * Math.floor(Date.now() / 1000),\n * null,\n * false,\n * ],\n * encryptSig: false,\n * maxFee: 1000000,\n * });\n * console.log(`Request TX ID: ${result.requestTxId}`);\n * ```\n */\n async requestAttestation(\n input: RequestAttestationInput\n ): Promise<RequestAttestationResult> {\n // Validate input\n validateAttestationRequest(input);\n\n // Encode arguments\n const argsBytes = encodeActionArgs(input.args);\n\n // Prepare named parameters for request_attestation action\n const params: Types.NamedParams[] = [{\n $data_provider: input.dataProvider,\n $stream_id: input.streamId,\n $action_name: input.actionName,\n $args_bytes: argsBytes,\n $encrypt_sig: input.encryptSig,\n $max_fee: input.maxFee,\n }];\n\n // Execute request_attestation action\n const result = await this.executeWithNamedParams('request_attestation', params);\n\n // Check for errors\n if (!result.data?.tx_hash) {\n throw new Error(\n 'Failed to request attestation: no transaction hash returned'\n );\n }\n\n // Return the 64-char hex tx_hash\n return {\n requestTxId: result.data.tx_hash,\n };\n }\n\n /**\n * Retrieve a complete signed attestation payload\n *\n * This fetches the signed attestation payload for a given request transaction ID.\n * The attestation must have been signed by the leader validator first.\n *\n * If the attestation is not yet signed, this will throw an error. Clients should\n * poll with exponential backoff or wait for 1-2 blocks after requesting.\n *\n * @param input - Request transaction ID\n * @returns Promise resolving to signed attestation payload\n * @throws Error if attestation not found or not yet signed\n *\n * @example\n * ```typescript\n * // Poll for signature\n * for (let i = 0; i < 15; i++) {\n * try {\n * const signed = await attestationAction.getSignedAttestation({\n * requestTxId: \"0x123...\",\n * });\n * console.log(`Payload: ${Buffer.from(signed.payload).toString('hex')}`);\n * break;\n * } catch (e) {\n * await new Promise(resolve => setTimeout(resolve, 2000));\n * }\n * }\n * ```\n */\n async getSignedAttestation(\n input: GetSignedAttestationInput\n ): Promise<SignedAttestationResult> {\n // Validate and normalize input\n const trimmed = input.requestTxId?.trim() || '';\n if (trimmed === '') {\n throw new Error('request_tx_id is required');\n }\n\n // Strip optional \"0x\" prefix and lowercase for normalization\n const normalizedRequestTxId = trimmed.startsWith('0x')\n ? trimmed.slice(2).toLowerCase()\n : trimmed.toLowerCase();\n\n // Call get_signed_attestation view action\n const result = await this.call<Array<{ payload: string | Uint8Array }>>(\n 'get_signed_attestation',\n { $request_tx_id: normalizedRequestTxId }\n );\n\n // Extract the right value from Either, or throw if Left\n const data = result.throw();\n\n // The action returns an array of rows - extract the first row\n if (!data || !Array.isArray(data) || data.length === 0) {\n throw new Error('No attestation found for request_tx_id - may not exist or is not yet signed');\n }\n\n const row = data[0];\n if (!row || !row.payload) {\n throw new Error('No payload in attestation row');\n }\n\n // Decode base64 to bytes\n let payloadBytes: Uint8Array;\n const payloadValue = row.payload;\n\n if (typeof payloadValue === 'string') {\n // Node.js environment\n if (typeof Buffer !== 'undefined') {\n payloadBytes = new Uint8Array(Buffer.from(payloadValue, 'base64'));\n } else {\n // Browser environment\n const binaryString = atob(payloadValue);\n payloadBytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n payloadBytes[i] = binaryString.charCodeAt(i);\n }\n }\n } else if (payloadValue instanceof Uint8Array) {\n // Already decoded\n payloadBytes = payloadValue;\n } else {\n throw new Error(`Unexpected payload type: ${typeof payloadValue}`);\n }\n\n return {\n payload: payloadBytes,\n };\n }\n\n /**\n * List attestation metadata with optional filtering\n *\n * This returns metadata for attestations, optionally filtered by requester address.\n * Supports pagination and sorting.\n *\n * @param input - Filter and pagination parameters\n * @returns Promise resolving to array of attestation metadata\n * @throws Error if parameters are invalid\n *\n * @example\n * ```typescript\n * // List my recent attestations\n * const myAddress = new Uint8Array(Buffer.from(wallet.address.slice(2), 'hex'));\n * const attestations = await attestationAction.listAttestations({\n * requester: myAddress,\n * limit: 10,\n * offset: 0,\n * orderBy: \"created_height desc\",\n * });\n *\n * attestations.forEach(att => {\n * console.log(`TX: ${att.requestTxId}, Height: ${att.createdHeight}`);\n * });\n * ```\n */\n async listAttestations(\n input: ListAttestationsInput\n ): Promise<AttestationMetadata[]> {\n // Validate input\n validateListAttestationsInput(input);\n\n // Set defaults\n const limit = input.limit ?? 5000;\n const offset = input.offset ?? 0;\n\n // Prepare parameters for list_attestations view action\n const params: Types.NamedParams = {\n $requester: input.requester ?? null,\n $limit: limit,\n $offset: offset,\n $order_by: input.orderBy ?? null,\n };\n\n // Call list_attestations view action\n const result = await this.call<any[]>('list_attestations', params);\n\n // Check for errors\n if (result.isLeft()) {\n throw new Error(\n `Failed to list attestations: HTTP status ${result.value}`\n );\n }\n\n // Extract the right value from Either\n const rows = result.value as unknown as any[];\n\n // If no rows, return empty array\n if (!rows || rows.length === 0) {\n return [];\n }\n\n // Parse rows into AttestationMetadata\n return rows.map((row: any, idx: number) => parseAttestationRow(row, idx));\n }\n}\n\n/**\n * Parse a single row from list_attestations result into AttestationMetadata\n *\n * Expected columns (in order):\n * 0. request_tx_id (TEXT)\n * 1. attestation_hash (BYTEA)\n * 2. requester (BYTEA)\n * 3. created_height (INT8)\n * 4. signed_height (INT8, nullable)\n * 5. encrypt_sig (BOOLEAN)\n */\nfunction parseAttestationRow(row: any, idx: number): AttestationMetadata {\n // kwil-js returns rows as objects with column names as keys\n // or as arrays depending on the query format\n let requestTxId: string;\n let attestationHash: Uint8Array;\n let requester: Uint8Array;\n let createdHeight: number;\n let signedHeight: number | null;\n let encryptSig: boolean;\n\n // Handle both array and object formats\n if (Array.isArray(row)) {\n // Array format: [col0, col1, col2, ...]\n if (row.length < 6) {\n throw new Error(\n `Row ${idx}: expected 6 columns, got ${row.length}`\n );\n }\n\n requestTxId = row[0];\n attestationHash = decodeBytea(row[1], idx, 'attestation_hash');\n requester = decodeBytea(row[2], idx, 'requester');\n createdHeight = parseInt(row[3], 10);\n signedHeight = row[4] !== null ? parseInt(row[4], 10) : null;\n encryptSig = row[5];\n } else {\n // Object format: { request_tx_id: ..., attestation_hash: ..., ... }\n requestTxId = row.request_tx_id;\n attestationHash = decodeBytea(row.attestation_hash, idx, 'attestation_hash');\n requester = decodeBytea(row.requester, idx, 'requester');\n createdHeight = parseInt(row.created_height, 10);\n signedHeight = row.signed_height !== null ? parseInt(row.signed_height, 10) : null;\n encryptSig = row.encrypt_sig;\n }\n\n return {\n requestTxId,\n attestationHash,\n requester,\n createdHeight,\n signedHeight,\n encryptSig,\n };\n}\n\n/**\n * Decode a BYTEA column from base64\n */\nfunction decodeBytea(value: any, rowIdx: number, colName: string): Uint8Array {\n if (value === null || value === undefined) {\n throw new Error(`Row ${rowIdx}: ${colName} is null or undefined`);\n }\n\n // If already Uint8Array, return as-is\n if (value instanceof Uint8Array) {\n return value;\n }\n\n // If string, decode from base64\n if (typeof value === 'string') {\n try {\n // Node.js environment\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(value, 'base64'));\n } else {\n // Browser environment\n const binaryString = atob(value);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n }\n } catch (err) {\n throw new Error(\n `Row ${rowIdx}: failed to decode ${colName} as base64: ${err}`\n );\n }\n }\n\n throw new Error(\n `Row ${rowIdx}: expected ${colName} to be string or Uint8Array, got ${typeof value}`\n );\n}\n\n// Inline unit tests\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest;\n\n describe('decodeBytea', () => {\n it('should decode base64 string', () => {\n const base64 = Buffer.from([1, 2, 3, 4]).toString('base64');\n const decoded = decodeBytea(base64, 0, 'test');\n expect(Array.from(decoded)).toEqual([1, 2, 3, 4]);\n });\n\n it('should return Uint8Array as-is', () => {\n const bytes = new Uint8Array([1, 2, 3, 4]);\n const decoded = decodeBytea(bytes, 0, 'test');\n expect(decoded).toBe(bytes);\n });\n\n it('should throw on null', () => {\n expect(() => decodeBytea(null, 0, 'test')).toThrow('null or undefined');\n });\n\n it('should throw on invalid type', () => {\n expect(() => decodeBytea(123, 0, 'test')).toThrow('expected test to be string or Uint8Array');\n });\n });\n\n describe('parseAttestationRow', () => {\n it('should parse array format row', () => {\n const row = [\n 'tx123',\n Buffer.from([1, 2, 3]).toString('base64'),\n Buffer.from([4, 5, 6]).toString('base64'),\n '100',\n '200',\n true,\n ];\n\n const metadata = parseAttestationRow(row, 0);\n\n expect(metadata.requestTxId).toBe('tx123');\n expect(Array.from(metadata.attestationHash)).toEqual([1, 2, 3]);\n expect(Array.from(metadata.requester)).toEqual([4, 5, 6]);\n expect(metadata.createdHeight).toBe(100);\n expect(metadata.signedHeight).toBe(200);\n expect(metadata.encryptSig).toBe(true);\n });\n\n it('should parse object format row', () => {\n const row = {\n request_tx_id: 'tx456',\n attestation_hash: Buffer.from([7, 8, 9]).toString('base64'),\n requester: Buffer.from([10, 11, 12]).toString('base64'),\n created_height: '300',\n signed_height: null,\n encrypt_sig: false,\n };\n\n const metadata = parseAttestationRow(row, 0);\n\n expect(metadata.requestTxId).toBe('tx456');\n expect(Array.from(metadata.attestationHash)).toEqual([7, 8, 9]);\n expect(Array.from(metadata.requester)).toEqual([10, 11, 12]);\n expect(metadata.createdHeight).toBe(300);\n expect(metadata.signedHeight).toBe(null);\n expect(metadata.encryptSig).toBe(false);\n });\n });\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["/**\n * Attestation action implementation\n *\n * This module provides methods for requesting, retrieving, and listing attestations.\n * Attestations are cryptographically signed proofs of query results that can be\n * consumed by smart contracts and external applications.\n */\n\nimport { Types, Utils } from '@trufnetwork/kwil-js';\nimport { Action } from './action';\nimport {\n RequestAttestationInput,\n RequestAttestationResult,\n GetSignedAttestationInput,\n SignedAttestationResult,\n ListAttestationsInput,\n AttestationMetadata,\n validateAttestationRequest,\n validateListAttestationsInput,\n} from '../types/attestation';\nimport { encodeActionArgs } from '../util/AttestationEncoding';\n\n/**\n * AttestationAction provides methods for working with data attestations\n *\n * Attestations enable validators to cryptographically sign query results,\n * providing verifiable proofs that can be used in smart contracts.\n *\n * @example\n * ```typescript\n * const client = new NodeTNClient({ ... });\n * const attestationAction = client.loadAttestationAction();\n *\n * // Request an attestation\n * const result = await attestationAction.requestAttestation({\n * dataProvider: \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\",\n * streamId: \"stai0000000000000000000000000000\",\n * actionName: \"get_record\",\n * args: [dataProvider, streamId, fromTime, toTime, null, false],\n * encryptSig: false,\n * maxFee: 1000000,\n * });\n *\n * // Wait for signing (1-2 blocks)\n * await new Promise(resolve => setTimeout(resolve, 10000));\n *\n * // Retrieve signed attestation\n * const signed = await attestationAction.getSignedAttestation({\n * requestTxId: result.requestTxId,\n * });\n * ```\n */\nexport class AttestationAction extends Action {\n /**\n * Request a signed attestation of query results\n *\n * This submits a transaction requesting that validators execute a query\n * and sign the results. The leader validator will sign the attestation\n * asynchronously (typically 1-2 blocks later).\n *\n * @param input - Attestation request parameters\n * @returns Promise resolving to request result with transaction ID\n * @throws Error if validation fails or transaction fails\n *\n * @example\n * ```typescript\n * const result = await attestationAction.requestAttestation({\n * dataProvider: \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\",\n * streamId: \"stai0000000000000000000000000000\",\n * actionName: \"get_record\",\n * args: [\n * \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\",\n * \"stai0000000000000000000000000000\",\n * Math.floor(Date.now() / 1000) - 86400, // 1 day ago\n * Math.floor(Date.now() / 1000),\n * null,\n * false,\n * ],\n * encryptSig: false,\n * maxFee: 1000000,\n * });\n * console.log(`Request TX ID: ${result.requestTxId}`);\n * ```\n */\n async requestAttestation(\n input: RequestAttestationInput\n ): Promise<RequestAttestationResult> {\n // Validate input\n validateAttestationRequest(input);\n\n // Encode arguments\n const argsBytes = encodeActionArgs(input.args);\n\n // Prepare named parameters for request_attestation action\n // Note: maxFee must be a string with NUMERIC type to encode as NUMERIC(788,0) for wei amounts\n const params: Types.NamedParams[] = [{\n $data_provider: input.dataProvider,\n $stream_id: input.streamId,\n $action_name: input.actionName,\n $args_bytes: argsBytes,\n $encrypt_sig: input.encryptSig,\n $max_fee: input.maxFee.toString(),\n }];\n\n // Specify types - maxFee needs NUMERIC(78,0) for large wei amounts\n const types = {\n $max_fee: Utils.DataType.Numeric(78, 0),\n };\n\n // Execute request_attestation action\n const result = await this.executeWithNamedParams('request_attestation', params, types);\n\n // Check for errors\n if (!result.data?.tx_hash) {\n throw new Error(\n 'Failed to request attestation: no transaction hash returned'\n );\n }\n\n // Return the 64-char hex tx_hash\n return {\n requestTxId: result.data.tx_hash,\n };\n }\n\n /**\n * Retrieve a complete signed attestation payload\n *\n * This fetches the signed attestation payload for a given request transaction ID.\n * The attestation must have been signed by the leader validator first.\n *\n * If the attestation is not yet signed, this will throw an error. Clients should\n * poll with exponential backoff or wait for 1-2 blocks after requesting.\n *\n * @param input - Request transaction ID\n * @returns Promise resolving to signed attestation payload\n * @throws Error if attestation not found or not yet signed\n *\n * @example\n * ```typescript\n * // Poll for signature\n * for (let i = 0; i < 15; i++) {\n * try {\n * const signed = await attestationAction.getSignedAttestation({\n * requestTxId: \"0x123...\",\n * });\n * console.log(`Payload: ${Buffer.from(signed.payload).toString('hex')}`);\n * break;\n * } catch (e) {\n * await new Promise(resolve => setTimeout(resolve, 2000));\n * }\n * }\n * ```\n */\n async getSignedAttestation(\n input: GetSignedAttestationInput\n ): Promise<SignedAttestationResult> {\n // Validate and normalize input\n const trimmed = input.requestTxId?.trim() || '';\n if (trimmed === '') {\n throw new Error('request_tx_id is required');\n }\n\n // Strip optional \"0x\" prefix and lowercase for normalization\n const normalizedRequestTxId = trimmed.startsWith('0x')\n ? trimmed.slice(2).toLowerCase()\n : trimmed.toLowerCase();\n\n // Call get_signed_attestation view action\n const result = await this.call<Array<{ payload: string | Uint8Array }>>(\n 'get_signed_attestation',\n { $request_tx_id: normalizedRequestTxId }\n );\n\n // Extract the right value from Either, or throw if Left\n const data = result.throw();\n\n // The action returns an array of rows - extract the first row\n if (!data || !Array.isArray(data) || data.length === 0) {\n throw new Error('No attestation found for request_tx_id - may not exist or is not yet signed');\n }\n\n const row = data[0];\n if (!row || !row.payload) {\n throw new Error('No payload in attestation row');\n }\n\n // Decode base64 to bytes\n let payloadBytes: Uint8Array;\n const payloadValue = row.payload;\n\n if (typeof payloadValue === 'string') {\n // Node.js environment\n if (typeof Buffer !== 'undefined') {\n payloadBytes = new Uint8Array(Buffer.from(payloadValue, 'base64'));\n } else {\n // Browser environment\n const binaryString = atob(payloadValue);\n payloadBytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n payloadBytes[i] = binaryString.charCodeAt(i);\n }\n }\n } else if (payloadValue instanceof Uint8Array) {\n // Already decoded\n payloadBytes = payloadValue;\n } else {\n throw new Error(`Unexpected payload type: ${typeof payloadValue}`);\n }\n\n return {\n payload: payloadBytes,\n };\n }\n\n /**\n * List attestation metadata with optional filtering\n *\n * This returns metadata for attestations, optionally filtered by requester address.\n * Supports pagination and sorting.\n *\n * @param input - Filter and pagination parameters\n * @returns Promise resolving to array of attestation metadata\n * @throws Error if parameters are invalid\n *\n * @example\n * ```typescript\n * // List my recent attestations\n * const myAddress = new Uint8Array(Buffer.from(wallet.address.slice(2), 'hex'));\n * const attestations = await attestationAction.listAttestations({\n * requester: myAddress,\n * limit: 10,\n * offset: 0,\n * orderBy: \"created_height desc\",\n * });\n *\n * attestations.forEach(att => {\n * console.log(`TX: ${att.requestTxId}, Height: ${att.createdHeight}`);\n * });\n * ```\n */\n async listAttestations(\n input: ListAttestationsInput\n ): Promise<AttestationMetadata[]> {\n // Validate input\n validateListAttestationsInput(input);\n\n // Set defaults\n const limit = input.limit ?? 5000;\n const offset = input.offset ?? 0;\n\n // Prepare parameters for list_attestations view action\n // Note: Empty Uint8Array represents BYTEA NULL (handled by kwil-js 0.9.10+)\n const params: Types.NamedParams = {\n $requester: input.requester ?? new Uint8Array(0),\n $limit: limit,\n $offset: offset,\n $order_by: input.orderBy ?? null,\n };\n\n // Call list_attestations view action\n const result = await this.call<any[]>('list_attestations', params);\n\n // Check for errors\n if (result.isLeft()) {\n throw new Error(\n `Failed to list attestations: HTTP status ${result.value}`\n );\n }\n\n // Extract the right value from Either\n // Note: result.value might be a getter function, so call it if needed\n const rightValue = typeof result.value === 'function' ? result.value() : result.value;\n const rows = Array.isArray(rightValue) ? rightValue : [];\n\n // If no rows, return empty array\n if (!rows || rows.length === 0) {\n return [];\n }\n\n // Parse rows into AttestationMetadata\n return rows.map((row: any, idx: number) => parseAttestationRow(row, idx));\n }\n}\n\n/**\n * Parse a single row from list_attestations result into AttestationMetadata\n *\n * Expected columns (in order):\n * 0. request_tx_id (TEXT)\n * 1. attestation_hash (BYTEA)\n * 2. requester (BYTEA)\n * 3. created_height (INT8)\n * 4. signed_height (INT8, nullable)\n * 5. encrypt_sig (BOOLEAN)\n */\nfunction parseAttestationRow(row: any, idx: number): AttestationMetadata {\n // kwil-js returns rows as objects with column names as keys\n // or as arrays depending on the query format\n let requestTxId: string;\n let attestationHash: Uint8Array;\n let requester: Uint8Array;\n let createdHeight: number;\n let signedHeight: number | null;\n let encryptSig: boolean;\n\n // Handle both array and object formats\n if (Array.isArray(row)) {\n // Array format: [col0, col1, col2, ...]\n if (row.length < 6) {\n throw new Error(\n `Row ${idx}: expected 6 columns, got ${row.length}`\n );\n }\n\n requestTxId = row[0];\n attestationHash = decodeBytea(row[1], idx, 'attestation_hash');\n requester = decodeBytea(row[2], idx, 'requester');\n createdHeight = parseInt(row[3], 10);\n signedHeight = row[4] !== null ? parseInt(row[4], 10) : null;\n encryptSig = row[5];\n } else {\n // Object format: { request_tx_id: ..., attestation_hash: ..., ... }\n requestTxId = row.request_tx_id;\n attestationHash = decodeBytea(row.attestation_hash, idx, 'attestation_hash');\n requester = decodeBytea(row.requester, idx, 'requester');\n createdHeight = parseInt(row.created_height, 10);\n signedHeight = row.signed_height !== null ? parseInt(row.signed_height, 10) : null;\n encryptSig = row.encrypt_sig;\n }\n\n return {\n requestTxId,\n attestationHash,\n requester,\n createdHeight,\n signedHeight,\n encryptSig,\n };\n}\n\n/**\n * Decode a BYTEA column from base64\n */\nfunction decodeBytea(value: any, rowIdx: number, colName: string): Uint8Array {\n if (value === null || value === undefined) {\n throw new Error(`Row ${rowIdx}: ${colName} is null or undefined`);\n }\n\n // If already Uint8Array, return as-is\n if (value instanceof Uint8Array) {\n return value;\n }\n\n // If string, decode from base64\n if (typeof value === 'string') {\n try {\n // Node.js environment\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(value, 'base64'));\n } else {\n // Browser environment\n const binaryString = atob(value);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n }\n } catch (err) {\n throw new Error(\n `Row ${rowIdx}: failed to decode ${colName} as base64: ${err}`\n );\n }\n }\n\n throw new Error(\n `Row ${rowIdx}: expected ${colName} to be string or Uint8Array, got ${typeof value}`\n );\n}\n\n// Inline unit tests\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest;\n\n describe('decodeBytea', () => {\n it('should decode base64 string', () => {\n const base64 = Buffer.from([1, 2, 3, 4]).toString('base64');\n const decoded = decodeBytea(base64, 0, 'test');\n expect(Array.from(decoded)).toEqual([1, 2, 3, 4]);\n });\n\n it('should return Uint8Array as-is', () => {\n const bytes = new Uint8Array([1, 2, 3, 4]);\n const decoded = decodeBytea(bytes, 0, 'test');\n expect(decoded).toBe(bytes);\n });\n\n it('should throw on null', () => {\n expect(() => decodeBytea(null, 0, 'test')).toThrow('null or undefined');\n });\n\n it('should throw on invalid type', () => {\n expect(() => decodeBytea(123, 0, 'test')).toThrow('expected test to be string or Uint8Array');\n });\n });\n\n describe('parseAttestationRow', () => {\n it('should parse array format row', () => {\n const row = [\n 'tx123',\n Buffer.from([1, 2, 3]).toString('base64'),\n Buffer.from([4, 5, 6]).toString('base64'),\n '100',\n '200',\n true,\n ];\n\n const metadata = parseAttestationRow(row, 0);\n\n expect(metadata.requestTxId).toBe('tx123');\n expect(Array.from(metadata.attestationHash)).toEqual([1, 2, 3]);\n expect(Array.from(metadata.requester)).toEqual([4, 5, 6]);\n expect(metadata.createdHeight).toBe(100);\n expect(metadata.signedHeight).toBe(200);\n expect(metadata.encryptSig).toBe(true);\n });\n\n it('should parse object format row', () => {\n const row = {\n request_tx_id: 'tx456',\n attestation_hash: Buffer.from([7, 8, 9]).toString('base64'),\n requester: Buffer.from([10, 11, 12]).toString('base64'),\n created_height: '300',\n signed_height: null,\n encrypt_sig: false,\n };\n\n const metadata = parseAttestationRow(row, 0);\n\n expect(metadata.requestTxId).toBe('tx456');\n expect(Array.from(metadata.attestationHash)).toEqual([7, 8, 9]);\n expect(Array.from(metadata.requester)).toEqual([10, 11, 12]);\n expect(metadata.createdHeight).toBe(300);\n expect(metadata.signedHeight).toBe(null);\n expect(metadata.encryptSig).toBe(false);\n });\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/contracts-api/transactionAction.ts
|
|
21
|
+
var transactionAction_exports = {};
|
|
22
|
+
__export(transactionAction_exports, {
|
|
23
|
+
TransactionAction: () => TransactionAction
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(transactionAction_exports);
|
|
26
|
+
var TransactionAction = class _TransactionAction {
|
|
27
|
+
kwilClient;
|
|
28
|
+
kwilSigner;
|
|
29
|
+
constructor(kwilClient, kwilSigner) {
|
|
30
|
+
this.kwilClient = kwilClient;
|
|
31
|
+
this.kwilSigner = kwilSigner;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Fetches detailed transaction information by transaction hash
|
|
35
|
+
*
|
|
36
|
+
* @param input Transaction query input containing tx hash
|
|
37
|
+
* @returns Promise resolving to transaction event with fee details
|
|
38
|
+
* @throws Error if transaction not found or query fails
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const txAction = client.loadTransactionAction();
|
|
43
|
+
* const txEvent = await txAction.getTransactionEvent({
|
|
44
|
+
* txId: "0xabcdef123456..."
|
|
45
|
+
* });
|
|
46
|
+
* console.log(`Method: ${txEvent.method}, Fee: ${txEvent.feeAmount} TRUF`);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
async getTransactionEvent(input) {
|
|
50
|
+
if (!input.txId || input.txId.trim() === "") {
|
|
51
|
+
throw new Error("tx_id is required");
|
|
52
|
+
}
|
|
53
|
+
const result = await this.kwilClient.call(
|
|
54
|
+
{
|
|
55
|
+
namespace: "main",
|
|
56
|
+
name: "get_transaction_event",
|
|
57
|
+
inputs: {
|
|
58
|
+
$tx_id: input.txId
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
this.kwilSigner
|
|
62
|
+
);
|
|
63
|
+
if (result.status !== 200) {
|
|
64
|
+
throw new Error(`Failed to get transaction event: HTTP ${result.status}`);
|
|
65
|
+
}
|
|
66
|
+
if (!result.data?.result || result.data.result.length === 0) {
|
|
67
|
+
throw new Error(`Transaction not found: ${input.txId}`);
|
|
68
|
+
}
|
|
69
|
+
const row = result.data.result[0];
|
|
70
|
+
if (!row.method || typeof row.method !== "string" || row.method.trim() === "") {
|
|
71
|
+
throw new Error(`Missing or invalid method field (tx: ${row.tx_id})`);
|
|
72
|
+
}
|
|
73
|
+
if (!row.caller || typeof row.caller !== "string" || row.caller.trim() === "") {
|
|
74
|
+
throw new Error(`Missing or invalid caller field (tx: ${row.tx_id})`);
|
|
75
|
+
}
|
|
76
|
+
if (row.fee_amount === null || row.fee_amount === void 0) {
|
|
77
|
+
throw new Error(`Missing fee_amount field (tx: ${row.tx_id})`);
|
|
78
|
+
}
|
|
79
|
+
const feeAmount = typeof row.fee_amount === "string" ? row.fee_amount : String(row.fee_amount);
|
|
80
|
+
const feeAmountNum = Number(feeAmount);
|
|
81
|
+
if (isNaN(feeAmountNum) || !Number.isFinite(feeAmountNum)) {
|
|
82
|
+
throw new Error(`Invalid fee_amount (not numeric): ${row.fee_amount} (tx: ${row.tx_id})`);
|
|
83
|
+
}
|
|
84
|
+
if (feeAmountNum < 0) {
|
|
85
|
+
throw new Error(`Invalid fee_amount (negative): ${row.fee_amount} (tx: ${row.tx_id})`);
|
|
86
|
+
}
|
|
87
|
+
const feeDistributions = [];
|
|
88
|
+
if (row.fee_distributions && row.fee_distributions !== "") {
|
|
89
|
+
const parts = row.fee_distributions.split(",");
|
|
90
|
+
for (const part of parts) {
|
|
91
|
+
const trimmedPart = part.trim();
|
|
92
|
+
if (trimmedPart) {
|
|
93
|
+
const colonIndex = trimmedPart.indexOf(":");
|
|
94
|
+
if (colonIndex === -1) {
|
|
95
|
+
throw new Error(`Invalid fee distribution format (missing colon): ${trimmedPart} (tx: ${row.tx_id})`);
|
|
96
|
+
}
|
|
97
|
+
const recipient = trimmedPart.substring(0, colonIndex).trim();
|
|
98
|
+
const amount = trimmedPart.substring(colonIndex + 1).trim();
|
|
99
|
+
if (!recipient || !amount) {
|
|
100
|
+
throw new Error(`Invalid fee distribution entry (empty recipient or amount): ${trimmedPart} (tx: ${row.tx_id})`);
|
|
101
|
+
}
|
|
102
|
+
const amt = Number(amount);
|
|
103
|
+
if (isNaN(amt) || !Number.isFinite(amt)) {
|
|
104
|
+
throw new Error(`Invalid fee distribution amount (not numeric): ${amount} (tx: ${row.tx_id})`);
|
|
105
|
+
}
|
|
106
|
+
if (amt < 0) {
|
|
107
|
+
throw new Error(`Invalid fee distribution amount (negative): ${amount} (tx: ${row.tx_id})`);
|
|
108
|
+
}
|
|
109
|
+
feeDistributions.push({ recipient, amount });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const blockHeight = typeof row.block_height === "number" ? row.block_height : parseInt(row.block_height, 10);
|
|
114
|
+
if (!Number.isFinite(blockHeight) || blockHeight < 0) {
|
|
115
|
+
throw new Error(`Invalid block height: ${row.block_height} (tx: ${row.tx_id})`);
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
txId: row.tx_id,
|
|
119
|
+
blockHeight,
|
|
120
|
+
method: row.method,
|
|
121
|
+
caller: row.caller,
|
|
122
|
+
feeAmount,
|
|
123
|
+
feeRecipient: row.fee_recipient || void 0,
|
|
124
|
+
metadata: row.metadata || void 0,
|
|
125
|
+
feeDistributions
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Creates a TransactionAction instance from an existing client and signer
|
|
130
|
+
*
|
|
131
|
+
* @param kwilClient The Kwil client (Web or Node)
|
|
132
|
+
* @param kwilSigner The Kwil signer for authentication
|
|
133
|
+
* @returns A new TransactionAction instance
|
|
134
|
+
*/
|
|
135
|
+
static fromClient(kwilClient, kwilSigner) {
|
|
136
|
+
return new _TransactionAction(kwilClient, kwilSigner);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=transactionAction.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/contracts-api/transactionAction.ts"],
|
|
4
|
+
"sourcesContent": ["import { KwilSigner, NodeKwil, WebKwil, Types } from \"@trufnetwork/kwil-js\";\r\nimport { TransactionEvent, FeeDistribution, GetTransactionEventInput } from \"../types/transaction\";\r\n\r\n/**\r\n * Database row structure returned from get_transaction_event action\r\n */\r\ninterface TransactionEventRow {\r\n tx_id: string;\r\n block_height: string | number;\r\n method: string;\r\n caller: string;\r\n fee_amount: string | number;\r\n fee_recipient?: string | null;\r\n metadata?: string | null;\r\n fee_distributions: string;\r\n}\r\n\r\n/**\r\n * TransactionAction provides methods for querying transaction ledger data\r\n */\r\nexport class TransactionAction {\r\n protected kwilClient: WebKwil | NodeKwil;\r\n protected kwilSigner: KwilSigner;\r\n\r\n constructor(kwilClient: WebKwil | NodeKwil, kwilSigner: KwilSigner) {\r\n this.kwilClient = kwilClient;\r\n this.kwilSigner = kwilSigner;\r\n }\r\n\r\n /**\r\n * Fetches detailed transaction information by transaction hash\r\n *\r\n * @param input Transaction query input containing tx hash\r\n * @returns Promise resolving to transaction event with fee details\r\n * @throws Error if transaction not found or query fails\r\n *\r\n * @example\r\n * ```typescript\r\n * const txAction = client.loadTransactionAction();\r\n * const txEvent = await txAction.getTransactionEvent({\r\n * txId: \"0xabcdef123456...\"\r\n * });\r\n * console.log(`Method: ${txEvent.method}, Fee: ${txEvent.feeAmount} TRUF`);\r\n * ```\r\n */\r\n async getTransactionEvent(input: GetTransactionEventInput): Promise<TransactionEvent> {\r\n if (!input.txId || input.txId.trim() === \"\") {\r\n throw new Error(\"tx_id is required\");\r\n }\r\n\r\n const result = await this.kwilClient.call(\r\n {\r\n namespace: \"main\",\r\n name: \"get_transaction_event\",\r\n inputs: {\r\n $tx_id: input.txId,\r\n },\r\n },\r\n this.kwilSigner\r\n );\r\n\r\n if (result.status !== 200) {\r\n throw new Error(`Failed to get transaction event: HTTP ${result.status}`);\r\n }\r\n\r\n if (!result.data?.result || result.data.result.length === 0) {\r\n throw new Error(`Transaction not found: ${input.txId}`);\r\n }\r\n\r\n const row = result.data.result[0] as TransactionEventRow;\r\n\r\n // Validate required fields\r\n if (!row.method || typeof row.method !== 'string' || row.method.trim() === '') {\r\n throw new Error(`Missing or invalid method field (tx: ${row.tx_id})`);\r\n }\r\n\r\n if (!row.caller || typeof row.caller !== 'string' || row.caller.trim() === '') {\r\n throw new Error(`Missing or invalid caller field (tx: ${row.tx_id})`);\r\n }\r\n\r\n if (row.fee_amount === null || row.fee_amount === undefined) {\r\n throw new Error(`Missing fee_amount field (tx: ${row.tx_id})`);\r\n }\r\n\r\n // Validate fee_amount is numeric (can be string or number)\r\n const feeAmount = typeof row.fee_amount === 'string' ? row.fee_amount : String(row.fee_amount);\r\n const feeAmountNum = Number(feeAmount);\r\n if (isNaN(feeAmountNum) || !Number.isFinite(feeAmountNum)) {\r\n throw new Error(`Invalid fee_amount (not numeric): ${row.fee_amount} (tx: ${row.tx_id})`);\r\n }\r\n if (feeAmountNum < 0) {\r\n throw new Error(`Invalid fee_amount (negative): ${row.fee_amount} (tx: ${row.tx_id})`);\r\n }\r\n\r\n // Parse fee_distributions string: \"recipient1:amount1,recipient2:amount2\"\r\n const feeDistributions: FeeDistribution[] = [];\r\n if (row.fee_distributions && row.fee_distributions !== \"\") {\r\n const parts = row.fee_distributions.split(\",\");\r\n for (const part of parts) {\r\n const trimmedPart = part.trim();\r\n if (trimmedPart) {\r\n // Split only on first colon to handle addresses with colons\r\n const colonIndex = trimmedPart.indexOf(\":\");\r\n if (colonIndex === -1) {\r\n throw new Error(`Invalid fee distribution format (missing colon): ${trimmedPart} (tx: ${row.tx_id})`);\r\n }\r\n\r\n const recipient = trimmedPart.substring(0, colonIndex).trim();\r\n const amount = trimmedPart.substring(colonIndex + 1).trim();\r\n\r\n if (!recipient || !amount) {\r\n throw new Error(`Invalid fee distribution entry (empty recipient or amount): ${trimmedPart} (tx: ${row.tx_id})`);\r\n }\r\n\r\n // Validate amount is numeric and non-negative\r\n const amt = Number(amount);\r\n if (isNaN(amt) || !Number.isFinite(amt)) {\r\n throw new Error(`Invalid fee distribution amount (not numeric): ${amount} (tx: ${row.tx_id})`);\r\n }\r\n if (amt < 0) {\r\n throw new Error(`Invalid fee distribution amount (negative): ${amount} (tx: ${row.tx_id})`);\r\n }\r\n\r\n feeDistributions.push({ recipient, amount });\r\n }\r\n }\r\n }\r\n\r\n // Validate block height\r\n const blockHeight = typeof row.block_height === 'number'\r\n ? row.block_height\r\n : parseInt(row.block_height, 10);\r\n if (!Number.isFinite(blockHeight) || blockHeight < 0) {\r\n throw new Error(`Invalid block height: ${row.block_height} (tx: ${row.tx_id})`);\r\n }\r\n\r\n return {\r\n txId: row.tx_id,\r\n blockHeight,\r\n method: row.method,\r\n caller: row.caller,\r\n feeAmount,\r\n feeRecipient: row.fee_recipient || undefined,\r\n metadata: row.metadata || undefined,\r\n feeDistributions,\r\n };\r\n }\r\n\r\n /**\r\n * Creates a TransactionAction instance from an existing client and signer\r\n *\r\n * @param kwilClient The Kwil client (Web or Node)\r\n * @param kwilSigner The Kwil signer for authentication\r\n * @returns A new TransactionAction instance\r\n */\r\n static fromClient(kwilClient: WebKwil | NodeKwil, kwilSigner: KwilSigner): TransactionAction {\r\n return new TransactionAction(kwilClient, kwilSigner);\r\n }\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -48,7 +48,8 @@ function validateAttestationRequest(input) {
|
|
|
48
48
|
if (input.encryptSig) {
|
|
49
49
|
throw new Error("encryption not implemented in MVP");
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
const maxFeeNum = typeof input.maxFee === "bigint" ? input.maxFee : typeof input.maxFee === "string" ? BigInt(input.maxFee) : BigInt(Math.floor(input.maxFee));
|
|
52
|
+
if (maxFeeNum < 0n) {
|
|
52
53
|
throw new Error(`max_fee must be non-negative, got ${input.maxFee}`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/types/attestation.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Type definitions for attestation operations\n *\n * Attestations enable validators to cryptographically sign query results,\n * providing verifiable proofs that can be consumed by smart contracts and\n * external applications.\n */\n\n/**\n * Input parameters for requesting an attestation\n */\nexport interface RequestAttestationInput {\n /**\n * Data provider address (0x-prefixed, 42 characters)\n * Example: \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\"\n */\n dataProvider: string;\n\n /**\n * Stream ID (32 characters)\n * Example: \"stai0000000000000000000000000000\"\n */\n streamId: string;\n\n /**\n * Action name to attest (must be in allowlist)\n * Example: \"get_record\", \"get_index\"\n */\n actionName: string;\n\n /**\n * Action arguments (will be encoded)\n * Must match the signature of the action\n */\n args: any[];\n\n /**\n * Whether to encrypt the signature (must be false in MVP)\n * Future: ECIES encryption to requester's public key\n */\n encryptSig: boolean;\n\n /**\n * Maximum fee willing to pay (in smallest token unit)\n * Transaction will abort if actual fee exceeds this\n */\n maxFee: number;\n}\n\n/**\n * Result of requesting an attestation\n */\nexport interface RequestAttestationResult {\n /**\n * Transaction ID for this attestation request\n * Use this to retrieve the signed attestation later\n */\n requestTxId: string;\n}\n\n/**\n * Input parameters for retrieving a signed attestation\n */\nexport interface GetSignedAttestationInput {\n /**\n * Transaction ID from request_attestation\n */\n requestTxId: string;\n}\n\n/**\n * Result of retrieving a signed attestation\n */\nexport interface SignedAttestationResult {\n /**\n * Complete attestation payload: canonical (8 fields) + signature\n *\n * Format: version | algo | height | provider | stream | action | args | result | signature\n *\n * This payload can be passed to EVM contracts for verification\n */\n payload: Uint8Array;\n}\n\n/**\n * Input parameters for listing attestations\n */\nexport interface ListAttestationsInput {\n /**\n * Optional: Filter by requester address (20 bytes)\n * If provided, only returns attestations requested by this address\n */\n requester?: Uint8Array;\n\n /**\n * Optional: Maximum number of results (1-5000, default 5000)\n */\n limit?: number;\n\n /**\n * Optional: Pagination offset (default 0)\n */\n offset?: number;\n\n /**\n * Optional: Sort order\n *\n * Allowed values:\n * - \"created_height asc\"\n * - \"created_height desc\"\n * - \"signed_height asc\"\n * - \"signed_height desc\"\n *\n * Case-insensitive\n */\n orderBy?: string;\n}\n\n/**\n * Metadata for a single attestation\n */\nexport interface AttestationMetadata {\n /**\n * Transaction ID for this attestation request\n */\n requestTxId: string;\n\n /**\n * Attestation hash (identifies this attestation)\n */\n attestationHash: Uint8Array;\n\n /**\n * Address of the requester (20 bytes)\n */\n requester: Uint8Array;\n\n /**\n * Block height when attestation was created\n */\n createdHeight: number;\n\n /**\n * Block height when attestation was signed (null if not yet signed)\n */\n signedHeight: number | null;\n\n /**\n * Whether signature is encrypted\n */\n encryptSig: boolean;\n}\n\n/**\n * Validates attestation request input\n *\n * @param input - The attestation request to validate\n * @throws Error if validation fails\n */\nexport function validateAttestationRequest(input: RequestAttestationInput): void {\n // Data provider validation\n if (input.dataProvider.length !== 42) {\n throw new Error(\n `data_provider must be 0x-prefixed 40 hex characters, got ${input.dataProvider.length} chars`\n );\n }\n\n if (!input.dataProvider.startsWith('0x')) {\n throw new Error('data_provider must start with 0x prefix');\n }\n\n // Validate hex after 0x prefix\n const hex = input.dataProvider.slice(2);\n if (!/^[0-9a-fA-F]{40}$/.test(hex)) {\n throw new Error('data_provider must contain valid hex characters after 0x prefix');\n }\n\n // Stream ID validation\n if (input.streamId.length !== 32) {\n throw new Error(`stream_id must be 32 characters, got ${input.streamId.length}`);\n }\n\n // Action name validation\n if (!input.actionName || input.actionName.trim() === '') {\n throw new Error('action_name cannot be empty');\n }\n\n // Encryption validation\n if (input.encryptSig) {\n throw new Error('encryption not implemented in MVP');\n }\n\n // Fee validation\n if (input.maxFee < 0) {\n throw new Error(`max_fee must be non-negative, got ${input.maxFee}`);\n }\n}\n\n/**\n * Whitelist of valid orderBy values (lowercase canonical form)\n */\nconst VALID_ORDER_BY_VALUES = [\n 'created_height asc',\n 'created_height desc',\n 'signed_height asc',\n 'signed_height desc',\n];\n\n/**\n * Validates orderBy parameter (case-insensitive)\n *\n * @param orderBy - The orderBy value to validate\n * @returns true if valid, false otherwise\n */\nexport function isValidOrderBy(orderBy: string): boolean {\n // Normalize to lowercase for case-insensitive comparison\n const normalized = orderBy.trim().toLowerCase();\n return VALID_ORDER_BY_VALUES.includes(normalized);\n}\n\n/**\n * Validates list attestations input\n *\n * @param input - The list attestations input to validate\n * @throws Error if validation fails\n */\nexport function validateListAttestationsInput(input: ListAttestationsInput): void {\n // Validate limit\n if (input.limit !== undefined) {\n if (input.limit < 1 || input.limit > 5000) {\n throw new Error('limit must be between 1 and 5000');\n }\n }\n\n // Validate offset\n if (input.offset !== undefined) {\n if (input.offset < 0) {\n throw new Error('offset must be non-negative');\n }\n }\n\n // Validate requester length\n if (input.requester !== undefined) {\n if (input.requester.length !== 20) {\n throw new Error('requester must be exactly 20 bytes');\n }\n }\n\n // Validate orderBy\n if (input.orderBy !== undefined) {\n if (!isValidOrderBy(input.orderBy)) {\n throw new Error(\n `Invalid orderBy value. Must be one of: ${VALID_ORDER_BY_VALUES.slice(0, 4).join(', ')}`\n );\n }\n }\n}\n\n// Inline unit tests\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest;\n\n describe('validateAttestationRequest', () => {\n it('should accept valid input', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000000,\n })\n ).not.toThrow();\n });\n\n it('should reject invalid data_provider length', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0xinvalid',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('data_provider must be 0x-prefixed 40 hex characters');\n });\n\n it('should reject data_provider without 0x prefix', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '4710a8d8f0d845da110086812a32de6d90d7ff5c00',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('data_provider must start with 0x prefix');\n });\n\n it('should reject data_provider with invalid hex', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0xGGGGa8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('data_provider must contain valid hex characters');\n });\n\n it('should reject short stream_id', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'short',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('stream_id must be 32 characters');\n });\n\n it('should reject long stream_id', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai00000000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('stream_id must be 32 characters');\n });\n\n it('should reject empty action_name', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: '',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('action_name cannot be empty');\n });\n\n it('should reject whitespace-only action_name', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: ' ',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('action_name cannot be empty');\n });\n\n it('should reject encryptSig=true', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: true,\n maxFee: 1000,\n })\n ).toThrow('encryption not implemented in MVP');\n });\n\n it('should reject negative maxFee', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: -1,\n })\n ).toThrow('max_fee must be non-negative');\n });\n });\n\n describe('isValidOrderBy', () => {\n it('should accept valid lowercase orderBy', () => {\n expect(isValidOrderBy('created_height asc')).toBe(true);\n expect(isValidOrderBy('created_height desc')).toBe(true);\n expect(isValidOrderBy('signed_height asc')).toBe(true);\n expect(isValidOrderBy('signed_height desc')).toBe(true);\n });\n\n it('should accept valid uppercase orderBy', () => {\n expect(isValidOrderBy('created_height ASC')).toBe(true);\n expect(isValidOrderBy('created_height DESC')).toBe(true);\n expect(isValidOrderBy('signed_height ASC')).toBe(true);\n expect(isValidOrderBy('signed_height DESC')).toBe(true);\n });\n\n it('should accept mixed case and trim whitespace', () => {\n expect(isValidOrderBy(' created_height ASC ')).toBe(true);\n expect(isValidOrderBy('Created_Height Desc')).toBe(true);\n expect(isValidOrderBy('SIGNED_HEIGHT asc')).toBe(true);\n expect(isValidOrderBy(' signed_height DESC ')).toBe(true);\n });\n\n it('should reject invalid orderBy', () => {\n expect(isValidOrderBy('invalid')).toBe(false);\n expect(isValidOrderBy('created_height')).toBe(false);\n expect(isValidOrderBy('created_height ascending')).toBe(false);\n expect(isValidOrderBy('')).toBe(false);\n });\n });\n\n describe('validateListAttestationsInput', () => {\n it('should accept valid input with all fields', () => {\n expect(() =>\n validateListAttestationsInput({\n requester: new Uint8Array(20),\n limit: 100,\n offset: 0,\n orderBy: 'created_height desc',\n })\n ).not.toThrow();\n });\n\n it('should accept valid input with no optional fields', () => {\n expect(() => validateListAttestationsInput({})).not.toThrow();\n });\n\n it('should reject limit < 1', () => {\n expect(() =>\n validateListAttestationsInput({\n limit: 0,\n })\n ).toThrow('limit must be between 1 and 5000');\n });\n\n it('should reject limit > 5000', () => {\n expect(() =>\n validateListAttestationsInput({\n limit: 5001,\n })\n ).toThrow('limit must be between 1 and 5000');\n });\n\n it('should reject negative offset', () => {\n expect(() =>\n validateListAttestationsInput({\n offset: -1,\n })\n ).toThrow('offset must be non-negative');\n });\n\n it('should reject requester != 20 bytes (too long)', () => {\n expect(() =>\n validateListAttestationsInput({\n requester: new Uint8Array(21),\n })\n ).toThrow('requester must be exactly 20 bytes');\n });\n\n it('should reject requester != 20 bytes (too short)', () => {\n expect(() =>\n validateListAttestationsInput({\n requester: new Uint8Array(19),\n })\n ).toThrow('requester must be exactly 20 bytes');\n });\n\n it('should reject invalid orderBy', () => {\n expect(() =>\n validateListAttestationsInput({\n orderBy: 'invalid',\n })\n ).toThrow('Invalid orderBy value');\n });\n });\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["/**\n * Type definitions for attestation operations\n *\n * Attestations enable validators to cryptographically sign query results,\n * providing verifiable proofs that can be consumed by smart contracts and\n * external applications.\n */\n\n/**\n * Input parameters for requesting an attestation\n */\nexport interface RequestAttestationInput {\n /**\n * Data provider address (0x-prefixed, 42 characters)\n * Example: \"0x4710a8d8f0d845da110086812a32de6d90d7ff5c\"\n */\n dataProvider: string;\n\n /**\n * Stream ID (32 characters)\n * Example: \"stai0000000000000000000000000000\"\n */\n streamId: string;\n\n /**\n * Action name to attest (must be in allowlist)\n * Example: \"get_record\", \"get_index\"\n */\n actionName: string;\n\n /**\n * Action arguments (will be encoded)\n * Must match the signature of the action\n */\n args: any[];\n\n /**\n * Whether to encrypt the signature (must be false in MVP)\n * Future: ECIES encryption to requester's public key\n */\n encryptSig: boolean;\n\n /**\n * Maximum fee willing to pay (in wei, as NUMERIC(78,0))\n * Accepts number, string, or bigint for large values (up to 40 TRUF = 40e18 wei)\n * Transaction will abort if actual fee exceeds this\n * Accepts number, string, or bigint for large values\n */\n maxFee: number | string | bigint;\n}\n\n/**\n * Result of requesting an attestation\n */\nexport interface RequestAttestationResult {\n /**\n * Transaction ID for this attestation request\n * Use this to retrieve the signed attestation later\n */\n requestTxId: string;\n}\n\n/**\n * Input parameters for retrieving a signed attestation\n */\nexport interface GetSignedAttestationInput {\n /**\n * Transaction ID from request_attestation\n */\n requestTxId: string;\n}\n\n/**\n * Result of retrieving a signed attestation\n */\nexport interface SignedAttestationResult {\n /**\n * Complete attestation payload: canonical (8 fields) + signature\n *\n * Format: version | algo | height | provider | stream | action | args | result | signature\n *\n * This payload can be passed to EVM contracts for verification\n */\n payload: Uint8Array;\n}\n\n/**\n * Input parameters for listing attestations\n */\nexport interface ListAttestationsInput {\n /**\n * Optional: Filter by requester address (20 bytes)\n * If provided, only returns attestations requested by this address\n */\n requester?: Uint8Array;\n\n /**\n * Optional: Maximum number of results (1-5000, default 5000)\n */\n limit?: number;\n\n /**\n * Optional: Pagination offset (default 0)\n */\n offset?: number;\n\n /**\n * Optional: Sort order\n *\n * Allowed values:\n * - \"created_height asc\"\n * - \"created_height desc\"\n * - \"signed_height asc\"\n * - \"signed_height desc\"\n *\n * Case-insensitive\n */\n orderBy?: string;\n}\n\n/**\n * Metadata for a single attestation\n */\nexport interface AttestationMetadata {\n /**\n * Transaction ID for this attestation request\n */\n requestTxId: string;\n\n /**\n * Attestation hash (identifies this attestation)\n */\n attestationHash: Uint8Array;\n\n /**\n * Address of the requester (20 bytes)\n */\n requester: Uint8Array;\n\n /**\n * Block height when attestation was created\n */\n createdHeight: number;\n\n /**\n * Block height when attestation was signed (null if not yet signed)\n */\n signedHeight: number | null;\n\n /**\n * Whether signature is encrypted\n */\n encryptSig: boolean;\n}\n\n/**\n * Validates attestation request input\n *\n * @param input - The attestation request to validate\n * @throws Error if validation fails\n */\nexport function validateAttestationRequest(input: RequestAttestationInput): void {\n // Data provider validation\n if (input.dataProvider.length !== 42) {\n throw new Error(\n `data_provider must be 0x-prefixed 40 hex characters, got ${input.dataProvider.length} chars`\n );\n }\n\n if (!input.dataProvider.startsWith('0x')) {\n throw new Error('data_provider must start with 0x prefix');\n }\n\n // Validate hex after 0x prefix\n const hex = input.dataProvider.slice(2);\n if (!/^[0-9a-fA-F]{40}$/.test(hex)) {\n throw new Error('data_provider must contain valid hex characters after 0x prefix');\n }\n\n // Stream ID validation\n if (input.streamId.length !== 32) {\n throw new Error(`stream_id must be 32 characters, got ${input.streamId.length}`);\n }\n\n // Action name validation\n if (!input.actionName || input.actionName.trim() === '') {\n throw new Error('action_name cannot be empty');\n }\n\n // Encryption validation\n if (input.encryptSig) {\n throw new Error('encryption not implemented in MVP');\n }\n\n // Fee validation - handle number, string, or bigint\n const maxFeeNum = typeof input.maxFee === 'bigint'\n ? input.maxFee\n : typeof input.maxFee === 'string'\n ? BigInt(input.maxFee)\n : BigInt(Math.floor(input.maxFee));\n\n if (maxFeeNum < 0n) {\n throw new Error(`max_fee must be non-negative, got ${input.maxFee}`);\n }\n}\n\n/**\n * Whitelist of valid orderBy values (lowercase canonical form)\n */\nconst VALID_ORDER_BY_VALUES = [\n 'created_height asc',\n 'created_height desc',\n 'signed_height asc',\n 'signed_height desc',\n];\n\n/**\n * Validates orderBy parameter (case-insensitive)\n *\n * @param orderBy - The orderBy value to validate\n * @returns true if valid, false otherwise\n */\nexport function isValidOrderBy(orderBy: string): boolean {\n // Normalize to lowercase for case-insensitive comparison\n const normalized = orderBy.trim().toLowerCase();\n return VALID_ORDER_BY_VALUES.includes(normalized);\n}\n\n/**\n * Validates list attestations input\n *\n * @param input - The list attestations input to validate\n * @throws Error if validation fails\n */\nexport function validateListAttestationsInput(input: ListAttestationsInput): void {\n // Validate limit\n if (input.limit !== undefined) {\n if (input.limit < 1 || input.limit > 5000) {\n throw new Error('limit must be between 1 and 5000');\n }\n }\n\n // Validate offset\n if (input.offset !== undefined) {\n if (input.offset < 0) {\n throw new Error('offset must be non-negative');\n }\n }\n\n // Validate requester length\n if (input.requester !== undefined) {\n if (input.requester.length !== 20) {\n throw new Error('requester must be exactly 20 bytes');\n }\n }\n\n // Validate orderBy\n if (input.orderBy !== undefined) {\n if (!isValidOrderBy(input.orderBy)) {\n throw new Error(\n `Invalid orderBy value. Must be one of: ${VALID_ORDER_BY_VALUES.slice(0, 4).join(', ')}`\n );\n }\n }\n}\n\n// Inline unit tests\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest;\n\n describe('validateAttestationRequest', () => {\n it('should accept valid input', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000000,\n })\n ).not.toThrow();\n });\n\n it('should reject invalid data_provider length', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0xinvalid',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('data_provider must be 0x-prefixed 40 hex characters');\n });\n\n it('should reject data_provider without 0x prefix', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '4710a8d8f0d845da110086812a32de6d90d7ff5c00',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('data_provider must start with 0x prefix');\n });\n\n it('should reject data_provider with invalid hex', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0xGGGGa8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('data_provider must contain valid hex characters');\n });\n\n it('should reject short stream_id', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'short',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('stream_id must be 32 characters');\n });\n\n it('should reject long stream_id', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai00000000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('stream_id must be 32 characters');\n });\n\n it('should reject empty action_name', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: '',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('action_name cannot be empty');\n });\n\n it('should reject whitespace-only action_name', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: ' ',\n args: [],\n encryptSig: false,\n maxFee: 1000,\n })\n ).toThrow('action_name cannot be empty');\n });\n\n it('should reject encryptSig=true', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: true,\n maxFee: 1000,\n })\n ).toThrow('encryption not implemented in MVP');\n });\n\n it('should reject negative maxFee', () => {\n expect(() =>\n validateAttestationRequest({\n dataProvider: '0x4710a8d8f0d845da110086812a32de6d90d7ff5c',\n streamId: 'stai0000000000000000000000000000',\n actionName: 'get_record',\n args: [],\n encryptSig: false,\n maxFee: -1,\n })\n ).toThrow('max_fee must be non-negative');\n });\n });\n\n describe('isValidOrderBy', () => {\n it('should accept valid lowercase orderBy', () => {\n expect(isValidOrderBy('created_height asc')).toBe(true);\n expect(isValidOrderBy('created_height desc')).toBe(true);\n expect(isValidOrderBy('signed_height asc')).toBe(true);\n expect(isValidOrderBy('signed_height desc')).toBe(true);\n });\n\n it('should accept valid uppercase orderBy', () => {\n expect(isValidOrderBy('created_height ASC')).toBe(true);\n expect(isValidOrderBy('created_height DESC')).toBe(true);\n expect(isValidOrderBy('signed_height ASC')).toBe(true);\n expect(isValidOrderBy('signed_height DESC')).toBe(true);\n });\n\n it('should accept mixed case and trim whitespace', () => {\n expect(isValidOrderBy(' created_height ASC ')).toBe(true);\n expect(isValidOrderBy('Created_Height Desc')).toBe(true);\n expect(isValidOrderBy('SIGNED_HEIGHT asc')).toBe(true);\n expect(isValidOrderBy(' signed_height DESC ')).toBe(true);\n });\n\n it('should reject invalid orderBy', () => {\n expect(isValidOrderBy('invalid')).toBe(false);\n expect(isValidOrderBy('created_height')).toBe(false);\n expect(isValidOrderBy('created_height ascending')).toBe(false);\n expect(isValidOrderBy('')).toBe(false);\n });\n });\n\n describe('validateListAttestationsInput', () => {\n it('should accept valid input with all fields', () => {\n expect(() =>\n validateListAttestationsInput({\n requester: new Uint8Array(20),\n limit: 100,\n offset: 0,\n orderBy: 'created_height desc',\n })\n ).not.toThrow();\n });\n\n it('should accept valid input with no optional fields', () => {\n expect(() => validateListAttestationsInput({})).not.toThrow();\n });\n\n it('should reject limit < 1', () => {\n expect(() =>\n validateListAttestationsInput({\n limit: 0,\n })\n ).toThrow('limit must be between 1 and 5000');\n });\n\n it('should reject limit > 5000', () => {\n expect(() =>\n validateListAttestationsInput({\n limit: 5001,\n })\n ).toThrow('limit must be between 1 and 5000');\n });\n\n it('should reject negative offset', () => {\n expect(() =>\n validateListAttestationsInput({\n offset: -1,\n })\n ).toThrow('offset must be non-negative');\n });\n\n it('should reject requester != 20 bytes (too long)', () => {\n expect(() =>\n validateListAttestationsInput({\n requester: new Uint8Array(21),\n })\n ).toThrow('requester must be exactly 20 bytes');\n });\n\n it('should reject requester != 20 bytes (too short)', () => {\n expect(() =>\n validateListAttestationsInput({\n requester: new Uint8Array(19),\n })\n ).toThrow('requester must be exactly 20 bytes');\n });\n\n it('should reject invalid orderBy', () => {\n expect(() =>\n validateListAttestationsInput({\n orderBy: 'invalid',\n })\n ).toThrow('Invalid orderBy value');\n });\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/types/transaction.ts"],
|
|
4
|
-
"sourcesContent": ["export interface LastTransaction {\r\n /** Block height */\r\n blockHeight: number;\r\n /** Which action was taken */\r\n method: string;\r\n /** Address that sent the on\u2010chain tx */\r\n sender: string;\r\n /** Hash of the on\u2010chain transaction */\r\n transactionHash: string;\r\n /** Millisecond timestamp from the block header */\r\n stampMs: number;\r\n}\r\n"],
|
|
4
|
+
"sourcesContent": ["export interface LastTransaction {\r\n /** Block height */\r\n blockHeight: number;\r\n /** Which action was taken */\r\n method: string;\r\n /** Address that sent the on\u2010chain tx */\r\n sender: string;\r\n /** Hash of the on\u2010chain transaction */\r\n transactionHash: string;\r\n /** Millisecond timestamp from the block header */\r\n stampMs: number;\r\n}\r\n\r\n/**\r\n * Represents a single fee distribution\r\n */\r\nexport interface FeeDistribution {\r\n /** Recipient Ethereum address */\r\n recipient: string;\r\n /** Amount as string (handles large numbers) */\r\n amount: string;\r\n}\r\n\r\n/**\r\n * Represents a single transaction event from the ledger\r\n *\r\n * Fee Fields Relationship:\r\n * - feeAmount: Total fee charged for the transaction (as string to handle large numbers)\r\n * - feeRecipient: Primary fee recipient address (if single recipient). May be undefined for:\r\n * 1. Transactions from fee-exempt wallets (system:network_writer role)\r\n * 2. Transactions with multiple fee distributions (use feeDistributions instead)\r\n * - feeDistributions: Array of fee distributions to multiple recipients\r\n * - Aggregated using string_agg() in get_transaction_event query\r\n * - Parsed from \"recipient1:amount1,recipient2:amount2\" format\r\n * - Sum of amounts in feeDistributions equals feeAmount (when present)\r\n * - Empty array when there are no distributions or single recipient (use feeRecipient)\r\n */\r\nexport interface TransactionEvent {\r\n /** Transaction hash (0x-prefixed) */\r\n txId: string;\r\n /** Block height when transaction was included */\r\n blockHeight: number;\r\n /** Method name (e.g., \"deployStream\", \"insertRecords\") */\r\n method: string;\r\n /** Ethereum address of caller (lowercase, 0x-prefixed) */\r\n caller: string;\r\n /**\r\n * Total fee amount as string (handles large numbers with 18 decimals)\r\n * Will be \"0\" for fee-exempt wallets (system:network_writer role)\r\n */\r\n feeAmount: string;\r\n /**\r\n * Primary fee recipient address (lowercase, 0x-prefixed)\r\n * Undefined when:\r\n * - Wallet is fee-exempt (feeAmount === \"0\")\r\n * - Fee has multiple distributions (check feeDistributions)\r\n */\r\n feeRecipient?: string;\r\n /** Optional metadata JSON (nullable) */\r\n metadata?: string;\r\n /**\r\n * Array of fee distributions to multiple recipients\r\n * Aggregated from transaction_event_distributions table using string_agg()\r\n */\r\n feeDistributions: FeeDistribution[];\r\n}\r\n\r\n/**\r\n * Input for getting transaction event\r\n */\r\nexport interface GetTransactionEventInput {\r\n /** Transaction hash (with or without 0x prefix) */\r\n txId: string;\r\n}\r\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -14,6 +14,7 @@ import { listStreams } from "./listStreams.mjs";
|
|
|
14
14
|
import { getLastTransactions } from "./getLastTransactions.mjs";
|
|
15
15
|
import { RoleManagement } from "../contracts-api/roleManagement.mjs";
|
|
16
16
|
import { AttestationAction } from "../contracts-api/attestationAction.mjs";
|
|
17
|
+
import { TransactionAction } from "../contracts-api/transactionAction.mjs";
|
|
17
18
|
var BaseTNClient = class {
|
|
18
19
|
constructor(options) {
|
|
19
20
|
__publicField(this, "kwilClient");
|
|
@@ -153,6 +154,16 @@ var BaseTNClient = class {
|
|
|
153
154
|
this.getKwilSigner()
|
|
154
155
|
);
|
|
155
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Loads the transaction action API, permitting transaction ledger queries.
|
|
159
|
+
* @returns An instance of TransactionAction.
|
|
160
|
+
*/
|
|
161
|
+
loadTransactionAction() {
|
|
162
|
+
return new TransactionAction(
|
|
163
|
+
this.getKwilClient(),
|
|
164
|
+
this.getKwilSigner()
|
|
165
|
+
);
|
|
166
|
+
}
|
|
156
167
|
/**
|
|
157
168
|
* Creates a new stream locator.
|
|
158
169
|
* @param streamId - The ID of the stream.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/client/client.ts"],
|
|
4
|
-
"sourcesContent": ["import { Client, KwilSigner, NodeKwil, WebKwil, Types, EnvironmentType } from \"@trufnetwork/kwil-js\";\nimport { ComposedAction, ListTaxonomiesByHeightParams, GetTaxonomiesForStreamsParams, TaxonomyQueryResult } from \"../contracts-api/composedAction\";\nimport { deployStream } from \"../contracts-api/deployStream\";\nimport { deleteStream } from \"../contracts-api/deleteStream\";\nimport { PrimitiveAction } from \"../contracts-api/primitiveAction\";\nimport { Action, ListMetadataByHeightParams, MetadataQueryResult } from \"../contracts-api/action\";\nimport { StreamType } from \"../contracts-api/contractValues\";\nimport { StreamLocator, TNStream } from \"../types/stream\";\nimport { EthereumAddress } from \"../util/EthereumAddress\";\nimport { StreamId } from \"../util/StreamId\";\nimport { listStreams } from \"./listStreams\";\nimport { getLastTransactions } from \"./getLastTransactions\";\nimport { RoleManagement } from \"../contracts-api/roleManagement\";\nimport { AttestationAction } from \"../contracts-api/attestationAction\";\nimport { OwnerIdentifier } from \"../types/role\";\n\nexport interface SignerInfo {\n // we need to have the address upfront to create the KwilSigner, instead of relying on the signer to return it asynchronously\n address: string;\n signer: Types.EthSigner;\n}\n\nexport type TNClientOptions = {\n endpoint: string;\n signerInfo: SignerInfo;\n} & Omit<Types.KwilConfig, \"kwilProvider\">;\n\nexport interface ListStreamsInput {\n dataProvider?: string;\n limit?: number;\n offset?: number;\n orderBy?: string;\n blockHeight?: number;\n}\n\n/**\n * @param dataProvider optional address; when omitted or null, returns for all providers\n * @param limitSize max rows to return (default 6, max 100)\n */\nexport interface GetLastTransactionsInput {\n dataProvider?: string;\n limitSize?: number;\n}\n\nexport abstract class BaseTNClient<T extends EnvironmentType> {\n protected kwilClient: Types.Kwil<T> | undefined;\n protected signerInfo: SignerInfo;\n\n protected constructor(options: TNClientOptions) {\n this.signerInfo = options.signerInfo;\n }\n\n /**\n * Waits for a transaction to be mined by TN.\n * @param txHash - The transaction hash to wait for.\n * @param timeout - The timeout in milliseconds.\n * @returns A promise that resolves to the transaction info receipt.\n */\n async waitForTx(txHash: string, timeout = 12000): Promise<Types.TxInfoReceipt> {\n return new Promise<Types.TxInfoReceipt>(async (resolve, reject) => {\n const interval = setInterval(async () => {\n const receipt = await this.getKwilClient()\n [\"txInfoClient\"](txHash)\n .catch(() => ({ data: undefined, status: undefined }));\n switch (receipt.status) {\n case 200:\n if (receipt.data?.tx_result?.log !== undefined && receipt.data?.tx_result?.log.includes(\"ERROR\")) {\n reject(\n new Error(\n `Transaction failed: status ${receipt.status} : log message ${receipt.data?.tx_result.log}`,\n ))\n } else {\n resolve(receipt.data!);\n }\n break;\n case undefined:\n break;\n default:\n reject(\n new Error(\n `Transaction failed: status ${receipt.status} : log message ${receipt.data?.tx_result.log}`,\n ),\n );\n }\n }, 1000);\n setTimeout(() => {\n clearInterval(interval);\n reject(new Error(\"Transaction failed: Timeout\"));\n }, timeout);\n });\n }\n\n /**\n * Returns the Kwil signer used by the client.\n * @returns An instance of KwilSigner.\n */\n getKwilSigner(): KwilSigner {\n return new KwilSigner(\n this.signerInfo.signer,\n this.address().getAddress(),\n );\n }\n\n /**\n * Returns the Kwil client used by the client.\n * @returns An instance of Kwil.\n * @throws If the Kwil client is not initialized.\n */\n getKwilClient(): Types.Kwil<EnvironmentType> {\n if (!this.kwilClient) {\n throw new Error(\"Kwil client not initialized\");\n }\n return this.kwilClient;\n }\n\n /**\n * Deploys a new stream.\n * @param streamId - The ID of the stream to deploy.\n * @param streamType - The type of the stream.\n * @param synchronous - Whether the deployment should be synchronous.\n * @param contractVersion\n * @returns A promise that resolves to a generic response containing the transaction receipt.\n */\n async deployStream(\n streamId: StreamId,\n streamType: StreamType,\n synchronous?: boolean,\n ): Promise<Types.GenericResponse<Types.TxReceipt>> {\n return await deployStream({\n streamId,\n streamType,\n synchronous,\n kwilClient: this.getKwilClient(),\n kwilSigner: this.getKwilSigner(),\n });\n }\n\n /**\n * Destroys a stream.\n * @param stream - The StreamLocator of the stream to destroy.\n * @param synchronous - Whether the destruction should be synchronous.\n * @returns A promise that resolves to a generic response containing the transaction receipt.\n */\n async destroyStream(\n stream: StreamLocator,\n synchronous?: boolean,\n ): Promise<Types.GenericResponse<Types.TxReceipt>> {\n return await deleteStream({\n stream,\n synchronous,\n kwilClient: this.getKwilClient(),\n kwilSigner: this.getKwilSigner(),\n });\n }\n\n /**\n * Loads an already deployed stream, permitting its API usage.\n * @returns An instance of IStream.\n */\n loadAction(): Action {\n return new Action(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Loads a primitive stream.\n * @returns An instance of IPrimitiveStream.\n */\n loadPrimitiveAction(): PrimitiveAction {\n return PrimitiveAction.fromStream(this.loadAction());\n }\n\n /**\n * Loads a composed stream.\n * @returns An instance of IComposedStream.\n */\n loadComposedAction(): ComposedAction {\n return ComposedAction.fromStream(this.loadAction());\n }\n\n /**\n * Loads the role management contract API, permitting its RBAC usage.\n */\n loadRoleManagementAction(): RoleManagement {\n return RoleManagement.fromClient(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Loads the attestation action API, permitting attestation operations.\n * @returns An instance of AttestationAction.\n */\n loadAttestationAction(): AttestationAction {\n return new AttestationAction(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Creates a new stream locator.\n * @param streamId - The ID of the stream.\n * @returns A StreamLocator object.\n */\n ownStreamLocator(streamId: StreamId): StreamLocator {\n return {\n streamId,\n dataProvider: this.address(),\n };\n }\n\n /**\n * Returns the address of the signer used by the client.\n * @returns An instance of EthereumAddress.\n */\n address(): EthereumAddress {\n return new EthereumAddress(this.signerInfo.address);\n }\n\n /**\n * Returns all streams from the TN network.\n * @param input - The input parameters for listing streams.\n * @returns A promise that resolves to a list of stream locators.\n */\n async getListStreams(input: ListStreamsInput): Promise<TNStream[]> {\n return listStreams(this.getKwilClient() as WebKwil | NodeKwil,this.getKwilSigner(),input);\n }\n\n /**\n * Returns the last write activity across streams.\n * @param input - The input parameters for getting last transactions.\n * @returns A promise that resolves to a list of last transactions.\n */\n async getLastTransactions(input: GetLastTransactionsInput): Promise<any[]> {\n return getLastTransactions(this.getKwilClient() as WebKwil | NodeKwil,this.getKwilSigner(),input);\n }\n\n /**\n * Lists taxonomies by height range for incremental synchronization.\n * High-level wrapper for ComposedAction.listTaxonomiesByHeight()\n * \n * @param params Height range and pagination parameters \n * @returns Promise resolving to taxonomy query results\n * \n * @example\n * ```typescript\n * const taxonomies = await client.listTaxonomiesByHeight({\n * fromHeight: 1000,\n * toHeight: 2000,\n * limit: 100,\n * latestOnly: true\n * });\n * ```\n */\n async listTaxonomiesByHeight(params: ListTaxonomiesByHeightParams = {}): Promise<TaxonomyQueryResult[]> {\n const composedAction = this.loadComposedAction();\n return composedAction.listTaxonomiesByHeight(params);\n }\n\n async listMetadataByHeight(params: ListMetadataByHeightParams = {}): Promise<MetadataQueryResult[]> {\n const action = this.loadAction();\n return action.listMetadataByHeight(params);\n }\n\n async getWalletBalance(chain: string, walletAddress: string) {\n const action = this.loadAction();\n return action.getWalletBalance(chain, walletAddress);\n }\n\n /**\n * Performs a withdrawal operation by bridging tokens\n * @param chain The chain identifier (e.g., \"sepolia\", \"mainnet\", \"polygon\", etc.)\n * @param amount The amount to withdraw\n * @returns Promise that resolves to the transaction hash, or throws on error\n */\n async withdraw(chain: string, amount: string, recipient: string): Promise<string> {\n const action = this.loadAction();\n \n // Bridge tokens in a single operation\n const bridgeResult = await action.bridgeTokens(chain, amount, recipient);\n if (!bridgeResult.data?.tx_hash) {\n throw new Error(\"Bridge tokens operation failed: no transaction hash returned\");\n }\n \n // Wait for bridge transaction to be mined - let waitForTx errors bubble up\n try {\n await this.waitForTx(bridgeResult.data.tx_hash);\n } catch (error) {\n throw new Error(`Bridge tokens transaction failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n \n // Return the transaction hash\n return bridgeResult.data.tx_hash;\n }\n\n /**\n * Lists wallet rewards for a specific wallet address on a blockchain network\n * @param chain The chain identifier (e.g., \"sepolia\", \"mainnet\", \"polygon\", etc.)\n * @param wallet The wallet address to list rewards for\n * @param withPending Whether to include pending rewards\n * @returns Promise that resolves to an array of rewards data\n */\n async listWalletRewards(chain: string, wallet: string, withPending: boolean): Promise<any[]> {\n const action = this.loadAction();\n return action.listWalletRewards(chain, wallet, withPending);\n }\n\n /**\n * Gets taxonomies for specific streams in batch.\n * High-level wrapper for ComposedAction.getTaxonomiesForStreams()\n * \n * @param params Stream locators and options\n * @returns Promise resolving to taxonomy query results\n * \n * @example\n * ```typescript\n * const streams = [\n * { dataProvider: provider1, streamId: streamId1 },\n * { dataProvider: provider2, streamId: streamId2 }\n * ];\n * const taxonomies = await client.getTaxonomiesForStreams({\n * streams,\n * latestOnly: true\n * });\n * ```\n */\n async getTaxonomiesForStreams(params: GetTaxonomiesForStreamsParams): Promise<TaxonomyQueryResult[]> {\n const composedAction = this.loadComposedAction();\n return composedAction.getTaxonomiesForStreams(params);\n }\n\n /**\n * Get the default chain id for a provider. Use with caution, as this decreases the security of the TN.\n * @param provider - The provider URL.\n * @returns A promise that resolves to the chain ID.\n */\n public static async getDefaultChainId(provider: string) {\n const kwilClient = new Client({\n kwilProvider: provider,\n });\n const chainInfo = await kwilClient[\"chainInfoClient\"]();\n return chainInfo.data?.chain_id;\n }\n\n /*\n * High-level role-management helpers. These wrap the lower-level\n * RoleManagement contract calls and expose a simpler API on the\n * TN client.\n */\n\n /** Grants a role to one or more wallets. */\n async grantRole(input: {\n owner: OwnerIdentifier;\n roleName: string;\n wallets: EthereumAddress | EthereumAddress[];\n synchronous?: boolean;\n }): Promise<string> {\n const rm = this.loadRoleManagementAction();\n const walletsArr: EthereumAddress[] = Array.isArray(input.wallets)\n ? input.wallets\n : [input.wallets];\n const tx = await rm.grantRole(\n {\n owner: input.owner,\n roleName: input.roleName,\n wallets: walletsArr,\n },\n input.synchronous,\n );\n return tx.data?.tx_hash as unknown as string;\n }\n\n /** Revokes a role from one or more wallets. */\n async revokeRole(input: {\n owner: OwnerIdentifier;\n roleName: string;\n wallets: EthereumAddress | EthereumAddress[];\n synchronous?: boolean;\n }): Promise<string> {\n const rm = this.loadRoleManagementAction();\n const walletsArr: EthereumAddress[] = Array.isArray(input.wallets)\n ? input.wallets\n : [input.wallets];\n const tx = await rm.revokeRole(\n {\n owner: input.owner,\n roleName: input.roleName,\n wallets: walletsArr,\n },\n input.synchronous,\n );\n return tx.data?.tx_hash as unknown as string;\n }\n\n /**\n * Checks if a wallet is member of a role.\n * Returns true if the wallet is a member.\n */\n async isMemberOf(input: {\n owner: OwnerIdentifier;\n roleName: string;\n wallet: EthereumAddress;\n }): Promise<boolean> {\n const rm = this.loadRoleManagementAction();\n const res = await rm.areMembersOf({\n owner: input.owner,\n roleName: input.roleName,\n wallets: [input.wallet],\n });\n return res.length > 0 && res[0].isMember;\n }\n\n /**\n * Lists role members \u2013 currently unsupported in the\n * smart-contract layer.\n */\n async listRoleMembers(input: {\n owner: OwnerIdentifier;\n roleName: string;\n limit?: number;\n offset?: number;\n }): Promise<import(\"../types/role\").RoleMember[]> {\n const rm = this.loadRoleManagementAction();\n return rm.listRoleMembers({\n owner: input.owner,\n roleName: input.roleName,\n limit: input.limit,\n offset: input.offset,\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { Client, KwilSigner, NodeKwil, WebKwil, Types, EnvironmentType } from \"@trufnetwork/kwil-js\";\nimport { ComposedAction, ListTaxonomiesByHeightParams, GetTaxonomiesForStreamsParams, TaxonomyQueryResult } from \"../contracts-api/composedAction\";\nimport { deployStream } from \"../contracts-api/deployStream\";\nimport { deleteStream } from \"../contracts-api/deleteStream\";\nimport { PrimitiveAction } from \"../contracts-api/primitiveAction\";\nimport { Action, ListMetadataByHeightParams, MetadataQueryResult } from \"../contracts-api/action\";\nimport { StreamType } from \"../contracts-api/contractValues\";\nimport { StreamLocator, TNStream } from \"../types/stream\";\nimport { EthereumAddress } from \"../util/EthereumAddress\";\nimport { StreamId } from \"../util/StreamId\";\nimport { listStreams } from \"./listStreams\";\nimport { getLastTransactions } from \"./getLastTransactions\";\nimport { RoleManagement } from \"../contracts-api/roleManagement\";\nimport { AttestationAction } from \"../contracts-api/attestationAction\";\nimport { TransactionAction } from \"../contracts-api/transactionAction\";\nimport { OwnerIdentifier } from \"../types/role\";\n\nexport interface SignerInfo {\n // we need to have the address upfront to create the KwilSigner, instead of relying on the signer to return it asynchronously\n address: string;\n signer: Types.EthSigner;\n}\n\nexport type TNClientOptions = {\n endpoint: string;\n signerInfo: SignerInfo;\n} & Omit<Types.KwilConfig, \"kwilProvider\">;\n\nexport interface ListStreamsInput {\n dataProvider?: string;\n limit?: number;\n offset?: number;\n orderBy?: string;\n blockHeight?: number;\n}\n\n/**\n * @param dataProvider optional address; when omitted or null, returns for all providers\n * @param limitSize max rows to return (default 6, max 100)\n */\nexport interface GetLastTransactionsInput {\n dataProvider?: string;\n limitSize?: number;\n}\n\nexport abstract class BaseTNClient<T extends EnvironmentType> {\n protected kwilClient: Types.Kwil<T> | undefined;\n protected signerInfo: SignerInfo;\n\n protected constructor(options: TNClientOptions) {\n this.signerInfo = options.signerInfo;\n }\n\n /**\n * Waits for a transaction to be mined by TN.\n * @param txHash - The transaction hash to wait for.\n * @param timeout - The timeout in milliseconds.\n * @returns A promise that resolves to the transaction info receipt.\n */\n async waitForTx(txHash: string, timeout = 12000): Promise<Types.TxInfoReceipt> {\n return new Promise<Types.TxInfoReceipt>(async (resolve, reject) => {\n const interval = setInterval(async () => {\n const receipt = await this.getKwilClient()\n [\"txInfoClient\"](txHash)\n .catch(() => ({ data: undefined, status: undefined }));\n switch (receipt.status) {\n case 200:\n if (receipt.data?.tx_result?.log !== undefined && receipt.data?.tx_result?.log.includes(\"ERROR\")) {\n reject(\n new Error(\n `Transaction failed: status ${receipt.status} : log message ${receipt.data?.tx_result.log}`,\n ))\n } else {\n resolve(receipt.data!);\n }\n break;\n case undefined:\n break;\n default:\n reject(\n new Error(\n `Transaction failed: status ${receipt.status} : log message ${receipt.data?.tx_result.log}`,\n ),\n );\n }\n }, 1000);\n setTimeout(() => {\n clearInterval(interval);\n reject(new Error(\"Transaction failed: Timeout\"));\n }, timeout);\n });\n }\n\n /**\n * Returns the Kwil signer used by the client.\n * @returns An instance of KwilSigner.\n */\n getKwilSigner(): KwilSigner {\n return new KwilSigner(\n this.signerInfo.signer,\n this.address().getAddress(),\n );\n }\n\n /**\n * Returns the Kwil client used by the client.\n * @returns An instance of Kwil.\n * @throws If the Kwil client is not initialized.\n */\n getKwilClient(): Types.Kwil<EnvironmentType> {\n if (!this.kwilClient) {\n throw new Error(\"Kwil client not initialized\");\n }\n return this.kwilClient;\n }\n\n /**\n * Deploys a new stream.\n * @param streamId - The ID of the stream to deploy.\n * @param streamType - The type of the stream.\n * @param synchronous - Whether the deployment should be synchronous.\n * @param contractVersion\n * @returns A promise that resolves to a generic response containing the transaction receipt.\n */\n async deployStream(\n streamId: StreamId,\n streamType: StreamType,\n synchronous?: boolean,\n ): Promise<Types.GenericResponse<Types.TxReceipt>> {\n return await deployStream({\n streamId,\n streamType,\n synchronous,\n kwilClient: this.getKwilClient(),\n kwilSigner: this.getKwilSigner(),\n });\n }\n\n /**\n * Destroys a stream.\n * @param stream - The StreamLocator of the stream to destroy.\n * @param synchronous - Whether the destruction should be synchronous.\n * @returns A promise that resolves to a generic response containing the transaction receipt.\n */\n async destroyStream(\n stream: StreamLocator,\n synchronous?: boolean,\n ): Promise<Types.GenericResponse<Types.TxReceipt>> {\n return await deleteStream({\n stream,\n synchronous,\n kwilClient: this.getKwilClient(),\n kwilSigner: this.getKwilSigner(),\n });\n }\n\n /**\n * Loads an already deployed stream, permitting its API usage.\n * @returns An instance of IStream.\n */\n loadAction(): Action {\n return new Action(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Loads a primitive stream.\n * @returns An instance of IPrimitiveStream.\n */\n loadPrimitiveAction(): PrimitiveAction {\n return PrimitiveAction.fromStream(this.loadAction());\n }\n\n /**\n * Loads a composed stream.\n * @returns An instance of IComposedStream.\n */\n loadComposedAction(): ComposedAction {\n return ComposedAction.fromStream(this.loadAction());\n }\n\n /**\n * Loads the role management contract API, permitting its RBAC usage.\n */\n loadRoleManagementAction(): RoleManagement {\n return RoleManagement.fromClient(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Loads the attestation action API, permitting attestation operations.\n * @returns An instance of AttestationAction.\n */\n loadAttestationAction(): AttestationAction {\n return new AttestationAction(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Loads the transaction action API, permitting transaction ledger queries.\n * @returns An instance of TransactionAction.\n */\n loadTransactionAction(): TransactionAction {\n return new TransactionAction(\n this.getKwilClient() as WebKwil | NodeKwil,\n this.getKwilSigner(),\n );\n }\n\n /**\n * Creates a new stream locator.\n * @param streamId - The ID of the stream.\n * @returns A StreamLocator object.\n */\n ownStreamLocator(streamId: StreamId): StreamLocator {\n return {\n streamId,\n dataProvider: this.address(),\n };\n }\n\n /**\n * Returns the address of the signer used by the client.\n * @returns An instance of EthereumAddress.\n */\n address(): EthereumAddress {\n return new EthereumAddress(this.signerInfo.address);\n }\n\n /**\n * Returns all streams from the TN network.\n * @param input - The input parameters for listing streams.\n * @returns A promise that resolves to a list of stream locators.\n */\n async getListStreams(input: ListStreamsInput): Promise<TNStream[]> {\n return listStreams(this.getKwilClient() as WebKwil | NodeKwil,this.getKwilSigner(),input);\n }\n\n /**\n * Returns the last write activity across streams.\n * @param input - The input parameters for getting last transactions.\n * @returns A promise that resolves to a list of last transactions.\n */\n async getLastTransactions(input: GetLastTransactionsInput): Promise<any[]> {\n return getLastTransactions(this.getKwilClient() as WebKwil | NodeKwil,this.getKwilSigner(),input);\n }\n\n /**\n * Lists taxonomies by height range for incremental synchronization.\n * High-level wrapper for ComposedAction.listTaxonomiesByHeight()\n * \n * @param params Height range and pagination parameters \n * @returns Promise resolving to taxonomy query results\n * \n * @example\n * ```typescript\n * const taxonomies = await client.listTaxonomiesByHeight({\n * fromHeight: 1000,\n * toHeight: 2000,\n * limit: 100,\n * latestOnly: true\n * });\n * ```\n */\n async listTaxonomiesByHeight(params: ListTaxonomiesByHeightParams = {}): Promise<TaxonomyQueryResult[]> {\n const composedAction = this.loadComposedAction();\n return composedAction.listTaxonomiesByHeight(params);\n }\n\n async listMetadataByHeight(params: ListMetadataByHeightParams = {}): Promise<MetadataQueryResult[]> {\n const action = this.loadAction();\n return action.listMetadataByHeight(params);\n }\n\n async getWalletBalance(chain: string, walletAddress: string) {\n const action = this.loadAction();\n return action.getWalletBalance(chain, walletAddress);\n }\n\n /**\n * Performs a withdrawal operation by bridging tokens\n * @param chain The chain identifier (e.g., \"sepolia\", \"mainnet\", \"polygon\", etc.)\n * @param amount The amount to withdraw\n * @returns Promise that resolves to the transaction hash, or throws on error\n */\n async withdraw(chain: string, amount: string, recipient: string): Promise<string> {\n const action = this.loadAction();\n \n // Bridge tokens in a single operation\n const bridgeResult = await action.bridgeTokens(chain, amount, recipient);\n if (!bridgeResult.data?.tx_hash) {\n throw new Error(\"Bridge tokens operation failed: no transaction hash returned\");\n }\n \n // Wait for bridge transaction to be mined - let waitForTx errors bubble up\n try {\n await this.waitForTx(bridgeResult.data.tx_hash);\n } catch (error) {\n throw new Error(`Bridge tokens transaction failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n \n // Return the transaction hash\n return bridgeResult.data.tx_hash;\n }\n\n /**\n * Lists wallet rewards for a specific wallet address on a blockchain network\n * @param chain The chain identifier (e.g., \"sepolia\", \"mainnet\", \"polygon\", etc.)\n * @param wallet The wallet address to list rewards for\n * @param withPending Whether to include pending rewards\n * @returns Promise that resolves to an array of rewards data\n */\n async listWalletRewards(chain: string, wallet: string, withPending: boolean): Promise<any[]> {\n const action = this.loadAction();\n return action.listWalletRewards(chain, wallet, withPending);\n }\n\n /**\n * Gets taxonomies for specific streams in batch.\n * High-level wrapper for ComposedAction.getTaxonomiesForStreams()\n * \n * @param params Stream locators and options\n * @returns Promise resolving to taxonomy query results\n * \n * @example\n * ```typescript\n * const streams = [\n * { dataProvider: provider1, streamId: streamId1 },\n * { dataProvider: provider2, streamId: streamId2 }\n * ];\n * const taxonomies = await client.getTaxonomiesForStreams({\n * streams,\n * latestOnly: true\n * });\n * ```\n */\n async getTaxonomiesForStreams(params: GetTaxonomiesForStreamsParams): Promise<TaxonomyQueryResult[]> {\n const composedAction = this.loadComposedAction();\n return composedAction.getTaxonomiesForStreams(params);\n }\n\n /**\n * Get the default chain id for a provider. Use with caution, as this decreases the security of the TN.\n * @param provider - The provider URL.\n * @returns A promise that resolves to the chain ID.\n */\n public static async getDefaultChainId(provider: string) {\n const kwilClient = new Client({\n kwilProvider: provider,\n });\n const chainInfo = await kwilClient[\"chainInfoClient\"]();\n return chainInfo.data?.chain_id;\n }\n\n /*\n * High-level role-management helpers. These wrap the lower-level\n * RoleManagement contract calls and expose a simpler API on the\n * TN client.\n */\n\n /** Grants a role to one or more wallets. */\n async grantRole(input: {\n owner: OwnerIdentifier;\n roleName: string;\n wallets: EthereumAddress | EthereumAddress[];\n synchronous?: boolean;\n }): Promise<string> {\n const rm = this.loadRoleManagementAction();\n const walletsArr: EthereumAddress[] = Array.isArray(input.wallets)\n ? input.wallets\n : [input.wallets];\n const tx = await rm.grantRole(\n {\n owner: input.owner,\n roleName: input.roleName,\n wallets: walletsArr,\n },\n input.synchronous,\n );\n return tx.data?.tx_hash as unknown as string;\n }\n\n /** Revokes a role from one or more wallets. */\n async revokeRole(input: {\n owner: OwnerIdentifier;\n roleName: string;\n wallets: EthereumAddress | EthereumAddress[];\n synchronous?: boolean;\n }): Promise<string> {\n const rm = this.loadRoleManagementAction();\n const walletsArr: EthereumAddress[] = Array.isArray(input.wallets)\n ? input.wallets\n : [input.wallets];\n const tx = await rm.revokeRole(\n {\n owner: input.owner,\n roleName: input.roleName,\n wallets: walletsArr,\n },\n input.synchronous,\n );\n return tx.data?.tx_hash as unknown as string;\n }\n\n /**\n * Checks if a wallet is member of a role.\n * Returns true if the wallet is a member.\n */\n async isMemberOf(input: {\n owner: OwnerIdentifier;\n roleName: string;\n wallet: EthereumAddress;\n }): Promise<boolean> {\n const rm = this.loadRoleManagementAction();\n const res = await rm.areMembersOf({\n owner: input.owner,\n roleName: input.roleName,\n wallets: [input.wallet],\n });\n return res.length > 0 && res[0].isMember;\n }\n\n /**\n * Lists role members \u2013 currently unsupported in the\n * smart-contract layer.\n */\n async listRoleMembers(input: {\n owner: OwnerIdentifier;\n roleName: string;\n limit?: number;\n offset?: number;\n }): Promise<import(\"../types/role\").RoleMember[]> {\n const rm = this.loadRoleManagementAction();\n return rm.listRoleMembers({\n owner: input.owner,\n roleName: input.roleName,\n limit: input.limit,\n offset: input.offset,\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -23,25 +23,46 @@ async function getLastTransactions(kwilClient, kwilSigner, input) {
|
|
|
23
23
|
}
|
|
24
24
|
return blockHeight;
|
|
25
25
|
});
|
|
26
|
-
const minBlock = Math.min(...blockHeights);
|
|
27
|
-
const maxBlock = Math.max(...blockHeights);
|
|
28
|
-
const txUrl = `${INDEXER_BASE}/v0/chain/transactions?from-block=${minBlock}&to-block=${maxBlock}&order=asc`;
|
|
29
|
-
const resp = await fetch(txUrl);
|
|
30
|
-
if (!resp.ok) {
|
|
31
|
-
throw new Error(`Indexer fetch failed: ${resp.status}`);
|
|
32
|
-
}
|
|
33
|
-
const json = await resp.json();
|
|
34
|
-
if (!json.ok) {
|
|
35
|
-
throw new Error("Indexer returned ok: false");
|
|
36
|
-
}
|
|
37
26
|
const blockToTx = /* @__PURE__ */ new Map();
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
let missingBlocks = [...blockHeights];
|
|
28
|
+
let attempts = 0;
|
|
29
|
+
const maxAttempts = 3;
|
|
30
|
+
while (missingBlocks.length > 0 && attempts < maxAttempts) {
|
|
31
|
+
attempts++;
|
|
32
|
+
const missingMin = Math.min(...missingBlocks);
|
|
33
|
+
const missingMax = Math.max(...missingBlocks);
|
|
34
|
+
const rangeUrl = `${INDEXER_BASE}/v0/chain/transactions?from-block=${missingMin}&to-block=${missingMax}&order=desc`;
|
|
35
|
+
try {
|
|
36
|
+
const rangeResp = await fetch(rangeUrl);
|
|
37
|
+
if (!rangeResp.ok) {
|
|
38
|
+
console.warn(`Indexer returned ${rangeResp.status} for range ${missingMin}-${missingMax}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const rangeJson = await rangeResp.json();
|
|
43
|
+
if (rangeJson.ok) {
|
|
44
|
+
for (const tx of rangeJson.data) {
|
|
45
|
+
if (!blockToTx.has(tx.block_height)) {
|
|
46
|
+
blockToTx.set(tx.block_height, {
|
|
47
|
+
hash: tx.hash,
|
|
48
|
+
sender: tx.sender,
|
|
49
|
+
stamp_ms: tx.stamp_ms
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
console.warn(`Indexer returned ok:false for range ${missingMin}-${missingMax}`);
|
|
55
|
+
}
|
|
56
|
+
} catch (parseError) {
|
|
57
|
+
console.warn(`Failed to parse JSON response for range ${missingMin}-${missingMax}:`, parseError);
|
|
58
|
+
}
|
|
59
|
+
} catch (fetchError) {
|
|
60
|
+
console.warn(`Failed to fetch transactions for range ${missingMin}-${missingMax}:`, fetchError);
|
|
61
|
+
}
|
|
62
|
+
const previousMissing = missingBlocks.length;
|
|
63
|
+
missingBlocks = blockHeights.filter((height) => !blockToTx.has(height));
|
|
64
|
+
if (missingBlocks.length === previousMissing) {
|
|
65
|
+
break;
|
|
45
66
|
}
|
|
46
67
|
}
|
|
47
68
|
return rows.map(({ created_at, method }) => {
|