Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Sale

Sale types, schemas, and utilities for the Gatekeeper protocol.

import { Sale, SaleKey } from '@sceneinfrastructure/sdk'

Try It

Sale Namespace Demo
Query sale configurations. Sales define pricing, time windows, fees, and vendor settings for ticket purchases.
List all sales for a contract.
await client.sale.listByContract({
  contractAddress,
  active: true,
  limit: 10,
})
Browser requests require CORS to be enabled.

Types

Sale

Complete sale configuration returned from the indexer.

import { Client } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: '...' })
 
// Sale objects are returned from indexer queries
const saleKeyId = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' as const
const sale = await client.sale.get({ saleKeyId })
 
if (sale) {
  console.log('Price:', sale.price)
  console.log('Quantity:', sale.quantity)
  console.log('Vendor:', sale.vendorAddress)
}
FieldTypeDescription
contractAddressAddressGatekeeper1155 contract
tokenIdbigintToken tier ID
currencyAddressAddressPayment currency
fundsRecipientAddressAddressFunds destination
vendorAddressAddressVendor address
vendorFeeBpsnumberVendor fee (basis points)
referralFeeBpsnumberReferral fee (basis points)
salesTaxBpsnumberSales tax (basis points)
noncebigintUnique nonce
pricebigintPrice per unit
quantitynumberAvailable quantity
startTimebigintSale start timestamp
endTimebigintSale end timestamp
approversAddress[]Authorized approvers

Additional indexer metadata:

  • saleKeyId - keccak256 hash of the SaleKey
  • gatekeeperAddress - Gatekeeper contract that registered the sale
  • saleType - Currency label emitted by the indexer
  • createdAt, updatedAt (plus block/log/tx fields) - indexer timestamps

SaleKey

The struct that uniquely identifies a sale in the Gatekeeper contract.

import type { Sale } from '@sceneinfrastructure/sdk'
 
const chainId = 8453 // Base
 
const saleKey = {
  token: '0x1234567890123456789012345678901234567890', // Your deployed contract
  tokenId: 1n,
  currency: '0x1111111111111111111111111111111111111111',
  fundsRecipient: '0x2345678901234567890123456789012345678901',
  vendor: '0x3456789012345678901234567890123456789012',
  vendorFeeBps: 0,
  referralFeeBps: 0,
  salesTaxBps: 0,
  nonce: 1n,
} as const satisfies Sale.SaleKey
FieldTypeDescription
tokenAddressContract address
tokenIdbigintToken ID
currencyAddressCurrency address
fundsRecipientAddressFunds recipient
vendorAddressVendor address
vendorFeeBpsnumberVendor fee BPS
referralFeeBpsnumberReferral fee BPS
salesTaxBpsnumberSales tax BPS
noncebigintUnique nonce

SaleKey is the immutable identity of a sale. Any field change produces a new saleKeyId, so keep the same key when calling updateSale. Use nonce to create multiple sales for the same token.


SaleState

Mutable sale configuration stored in the contract.

import type { Sale } from '@sceneinfrastructure/sdk'
 
const saleState: Sale.SaleState = {
  startTime: 1n,
  endTime: 9999999999n,
  quantity: 100,
  price: 10_000000n,
  approvers: ['0x1234567890123456789012345678901234567890'],
}
FieldTypeDescription
startTimebigintStart timestamp
endTimebigintEnd timestamp
quantitynumberAvailable quantity
pricebigintPrice per unit
approversAddress[]Authorized approvers

startTime must be non-zero; 0n is treated as "uninitialized" onchain.


PurchaseParams

Parameters for executing a purchase.

import type { Sale } from '@sceneinfrastructure/sdk'
 
const purchaseParams: Sale.PurchaseParams = {
  recipient: '0x1234567890123456789012345678901234567890',
  referrer: '0x0000000000000000000000000000000000000000',
  quantity: 2,
}
FieldTypeDescription
recipientAddressToken recipient
referrerAddressReferrer (or zero)
quantitynumberNumber to purchase

ApprovalSignatureParams

EIP-712 signature parameters for approved purchases.

import type { Sale } from '@sceneinfrastructure/sdk'
 
const signatureParams: Sale.ApprovalSignatureParams = {
  deadline: BigInt(Math.floor(Date.now() / 1000) + 900),
  salt: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
  signature: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12',
}
FieldTypeDescription
deadlinebigintSignature expiration
saltHexRandom bytes32
signatureHexECDSA signature

PurchaseResult

Price breakdown returned by getPrice.

import type { Sale } from '@sceneinfrastructure/sdk'
 
const result: Sale.PurchaseResult = {
  totalPrice: 10_200000n,
  subtotal: 10_000000n,
  protocolFee: 100000n,
  vendorFee: 50000n,
  referrerFee: 25000n,
  salesTax: 25000n,
}

Functions

toSaleKey

Converts a full Sale object to a SaleKey struct.

import { Client, Sale, SaleKey } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: '...' })
 
// Get a sale from the indexer using its saleKeyId
const saleKeyId = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' as const
const sale = await client.sale.get({ saleKeyId })
 
if (sale) {
  // Convert to SaleKey for contract interactions
  const saleKey = Sale.toSaleKey(sale)
  console.log('SaleKey:', saleKey)
}

SaleKey Module

generateId

Generates the keccak256 hash of a SaleKey struct.

import { SaleKey } from '@sceneinfrastructure/sdk'
 
const chainId = 8453 // Base
 
const saleKey = {
  token: '0x1234567890123456789012345678901234567890', // Your deployed contract
  tokenId: 1n,
  currency: '0x1111111111111111111111111111111111111111',
  fundsRecipient: '0x2345678901234567890123456789012345678901',
  vendor: '0x3456789012345678901234567890123456789012',
  vendorFeeBps: 0,
  referralFeeBps: 0,
  salesTaxBps: 0,
  nonce: 1n,
} as const
 
const id = SaleKey.generateId(saleKey)
console.log('Sale Key ID:', id)

Returns

Hex - keccak256 hash (bytes32)


Schemas

Zod schemas for runtime validation of sale data.

import { Sale } from '@sceneinfrastructure/sdk'

schema

The main schema for validating complete sale configurations.

import { Sale } from '@sceneinfrastructure/sdk'
 
const data = {
  contractAddress: '0x1234567890123456789012345678901234567890',
  tokenId: 1n,
  currencyAddress: '0xded683C101b0171aA42d90F5388b7A44a7D7c355',
  fundsRecipientAddress: '0x2345678901234567890123456789012345678901',
  vendorAddress: '0x3456789012345678901234567890123456789012',
  vendorFeeBps: 0,
  referralFeeBps: 0,
  salesTaxBps: 0,
  nonce: 1n,
  price: 10_000000n,
  quantity: 100,
  startTime: 1n,
  endTime: 9999999999n,
  approvers: [],
}
 
const result = Sale.schema.safeParse(data)
 
if (result.success) {
  console.log('Valid sale:', result.data.price)
} else {
  console.error('Validation errors:', result.error.issues)
}

saleKeySchema

Validates SaleKey structs for contract interactions.

import { Sale } from '@sceneinfrastructure/sdk'
 
const saleKey = Sale.saleKeySchema.parse({
  token: '0x1234567890123456789012345678901234567890',
  tokenId: 1n,
  currency: '0xded683C101b0171aA42d90F5388b7A44a7D7c355',
  fundsRecipient: '0x2345678901234567890123456789012345678901',
  vendor: '0x3456789012345678901234567890123456789012',
  vendorFeeBps: 0,
  referralFeeBps: 0,
  salesTaxBps: 0,
  nonce: 1n,
})
FieldTypeValidation
tokenAddressValid Ethereum address
tokenIdbigintBigInt
currencyAddressValid Ethereum address
fundsRecipientAddressValid Ethereum address
vendorAddressValid Ethereum address
vendorFeeBpsnumber0 to 4,294,967,295
referralFeeBpsnumber0 to 4,294,967,295
salesTaxBpsnumber0 to 4,294,967,295
noncebigintBigInt

saleStateSchema

Validates mutable sale state for registration and updates.

import { Sale } from '@sceneinfrastructure/sdk'
 
const saleState = Sale.saleStateSchema.parse({
  startTime: 1n,
  endTime: 9999999999n,
  quantity: 100,
  price: 10_000000n,
  approvers: ['0x1234567890123456789012345678901234567890'],
})
FieldTypeValidation
startTimebigintBigInt
endTimebigintBigInt
quantitynumber0 to 4,294,967,295
pricebigintBigInt
approversAddress[]Array of valid addresses

purchaseParamsSchema

Validates purchase parameters.

import { Sale } from '@sceneinfrastructure/sdk'
 
const params = Sale.purchaseParamsSchema.parse({
  recipient: '0x1234567890123456789012345678901234567890',
  referrer: '0x0000000000000000000000000000000000000000',
  quantity: 2,
})
FieldTypeValidation
recipientAddressValid Ethereum address
referrerAddressValid Ethereum address
quantitynumber1 to 65,535

approvalSignatureParamsSchema

Validates EIP-712 signature parameters for approved purchases.

import { Sale } from '@sceneinfrastructure/sdk'
 
const sigParams = Sale.approvalSignatureParamsSchema.parse({
  deadline: BigInt(Math.floor(Date.now() / 1000) + 900),
  salt: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
  signature: '0x...',
})
FieldTypeValidation
deadlinebigintBigInt
saltHexValid hex string (bytes32)
signatureHexValid hex string

purchaseResultSchema

Validates price breakdown results from getPrice.

import { Sale } from '@sceneinfrastructure/sdk'
 
const result = Sale.purchaseResultSchema.parse({
  totalPrice: 10_200000n,
  subtotal: 10_000000n,
  protocolFee: 100000n,
  vendorFee: 50000n,
  referrerFee: 25000n,
  salesTax: 25000n,
})
FieldTypeValidation
totalPricebigintBigInt
subtotalbigintBigInt
protocolFeebigintBigInt
vendorFeebigintBigInt
referrerFeebigintBigInt
salesTaxbigintBigInt

Read Operations

Query sale configurations from the indexer.

import { Client } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: '...' })

get

Get a sale by its key ID.

import { Client, SaleKey } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: 'https://ponder.mesh.xyz' })
 
const chainId = 8453 // Base
 
const saleKey = {
  token: '0x1234567890123456789012345678901234567890',
  tokenId: 1n,
  currency: '0x1111111111111111111111111111111111111111',
  fundsRecipient: '0x2345678901234567890123456789012345678901',
  vendor: '0x3456789012345678901234567890123456789012',
  vendorFeeBps: 0,
  referralFeeBps: 0,
  salesTaxBps: 0,
  nonce: 1n,
} as const
 
const saleKeyId = SaleKey.generateId(saleKey)
 
const sale = await client.sale.get({
  saleKeyId
})
 
if (sale) {
  console.log('Price:', sale.price)
  console.log('Quantity:', sale.quantity)
}

Parameters

ParameterTypeDescription
saleKeyIdHexThe keccak256 hash of the SaleKey

Returns

Sale | null - The sale configuration or null if not found.


getByKey

Get a sale by its SaleKey struct (convenience method).

import { Client } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: 'https://ponder.mesh.xyz' })
 
const chainId = 8453 // Base
 
const sale = await client.sale.getByKey({
  token: '0x1234567890123456789012345678901234567890',
  tokenId: 1n,
  currency: '0x1111111111111111111111111111111111111111',
  fundsRecipient: '0x2345678901234567890123456789012345678901',
  vendor: '0x3456789012345678901234567890123456789012',
  vendorFeeBps: 0,
  referralFeeBps: 0,
  salesTaxBps: 0,
  nonce: 1n,
})

Parameters

Takes a SaleKey struct directly instead of the hash.

Returns

Sale | null - The sale configuration or null if not found.


listByContract

List all sales for a contract.

import { Client } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: 'https://ponder.mesh.xyz' })
 
const sales = await client.sale.listByContract({
  contractAddress: '0x1234567890123456789012345678901234567890',
  limit: 20
})
 
for (const sale of sales) {
  console.log(`Token ${sale.tokenId}: ${sale.price} per ticket`)
}
 
// Filter to only active sales
const activeSales = await client.sale.listByContract({
  contractAddress: '0x1234567890123456789012345678901234567890',
  active: true
})

Parameters

ParameterTypeDefaultDescription
contractAddressAddressrequiredThe contract address
activeboolean-Filter to only active sales
limitnumber50Maximum results to return
offsetnumber0Number of results to skip
orderBy'createdAt' | 'price''createdAt'Sort field
order'asc' | 'desc''desc'Sort direction

Returns

Sale[] - Array of sale configurations.


listByVendor

List all sales where an address is the vendor.

import { Client } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: 'https://ponder.mesh.xyz' })
 
const sales = await client.sale.listByVendor({
  vendor: '0x2345678901234567890123456789012345678901',
  limit: 20
})
 
for (const sale of sales) {
  console.log(`Contract ${sale.contractAddress}: ${sale.vendorFeeBps} bps fee`)
}

Parameters

ParameterTypeDefaultDescription
vendorAddressrequiredThe vendor address
limitnumber50Maximum results to return
offsetnumber0Number of results to skip

Returns

Sale[] - Array of sale configurations.


listActive

List currently active sales.

import { Client } from '@sceneinfrastructure/sdk'
 
const client = Client.create({ url: 'https://ponder.mesh.xyz' })
 
// All active sales across all contracts
const activeSales = await client.sale.listActive({
  limit: 50
})
 
// Active sales for a specific contract
const contractActiveSales = await client.sale.listActive({
  contractAddress: '0x1234567890123456789012345678901234567890',
  limit: 20
})
 
for (const sale of contractActiveSales) {
  const now = BigInt(Math.floor(Date.now() / 1000))
  const endsIn = sale.endTime - now
  console.log(`Sale ends in ${endsIn} seconds`)
}

Parameters

ParameterTypeDefaultDescription
contractAddressAddress-Filter to specific contract
limitnumber50Maximum results to return
offsetnumber0Number of results to skip

Returns

Sale[] - Array of currently active sales (within start/end time window).