Sale
Sale types, schemas, and utilities for the Gatekeeper protocol.
import { Sale, SaleKey } from '@sceneinfrastructure/sdk'Try It
await client.sale.listByContract({
contractAddress,
active: true,
limit: 10,
})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)
}| Field | Type | Description |
|---|---|---|
contractAddress | Address | Gatekeeper1155 contract |
tokenId | bigint | Token tier ID |
currencyAddress | Address | Payment currency |
fundsRecipientAddress | Address | Funds destination |
vendorAddress | Address | Vendor address |
vendorFeeBps | number | Vendor fee (basis points) |
referralFeeBps | number | Referral fee (basis points) |
salesTaxBps | number | Sales tax (basis points) |
nonce | bigint | Unique nonce |
price | bigint | Price per unit |
quantity | number | Available quantity |
startTime | bigint | Sale start timestamp |
endTime | bigint | Sale end timestamp |
approvers | Address[] | Authorized approvers |
Additional indexer metadata:
saleKeyId- keccak256 hash of theSaleKeygatekeeperAddress- Gatekeeper contract that registered the salesaleType- Currency label emitted by the indexercreatedAt,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| Field | Type | Description |
|---|---|---|
token | Address | Contract address |
tokenId | bigint | Token ID |
currency | Address | Currency address |
fundsRecipient | Address | Funds recipient |
vendor | Address | Vendor address |
vendorFeeBps | number | Vendor fee BPS |
referralFeeBps | number | Referral fee BPS |
salesTaxBps | number | Sales tax BPS |
nonce | bigint | Unique 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'],
}| Field | Type | Description |
|---|---|---|
startTime | bigint | Start timestamp |
endTime | bigint | End timestamp |
quantity | number | Available quantity |
price | bigint | Price per unit |
approvers | Address[] | 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,
}| Field | Type | Description |
|---|---|---|
recipient | Address | Token recipient |
referrer | Address | Referrer (or zero) |
quantity | number | Number 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',
}| Field | Type | Description |
|---|---|---|
deadline | bigint | Signature expiration |
salt | Hex | Random bytes32 |
signature | Hex | ECDSA 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,
})| Field | Type | Validation |
|---|---|---|
token | Address | Valid Ethereum address |
tokenId | bigint | BigInt |
currency | Address | Valid Ethereum address |
fundsRecipient | Address | Valid Ethereum address |
vendor | Address | Valid Ethereum address |
vendorFeeBps | number | 0 to 4,294,967,295 |
referralFeeBps | number | 0 to 4,294,967,295 |
salesTaxBps | number | 0 to 4,294,967,295 |
nonce | bigint | BigInt |
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'],
})| Field | Type | Validation |
|---|---|---|
startTime | bigint | BigInt |
endTime | bigint | BigInt |
quantity | number | 0 to 4,294,967,295 |
price | bigint | BigInt |
approvers | Address[] | Array of valid addresses |
purchaseParamsSchema
Validates purchase parameters.
import { Sale } from '@sceneinfrastructure/sdk'
const params = Sale.purchaseParamsSchema.parse({
recipient: '0x1234567890123456789012345678901234567890',
referrer: '0x0000000000000000000000000000000000000000',
quantity: 2,
})| Field | Type | Validation |
|---|---|---|
recipient | Address | Valid Ethereum address |
referrer | Address | Valid Ethereum address |
quantity | number | 1 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...',
})| Field | Type | Validation |
|---|---|---|
deadline | bigint | BigInt |
salt | Hex | Valid hex string (bytes32) |
signature | Hex | Valid 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,
})| Field | Type | Validation |
|---|---|---|
totalPrice | bigint | BigInt |
subtotal | bigint | BigInt |
protocolFee | bigint | BigInt |
vendorFee | bigint | BigInt |
referrerFee | bigint | BigInt |
salesTax | bigint | BigInt |
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
| Parameter | Type | Description |
|---|---|---|
saleKeyId | Hex | The 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
| Parameter | Type | Default | Description |
|---|---|---|---|
contractAddress | Address | required | The contract address |
active | boolean | - | Filter to only active sales |
limit | number | 50 | Maximum results to return |
offset | number | 0 | Number 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
| Parameter | Type | Default | Description |
|---|---|---|---|
vendor | Address | required | The vendor address |
limit | number | 50 | Maximum results to return |
offset | number | 0 | Number 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
| Parameter | Type | Default | Description |
|---|---|---|---|
contractAddress | Address | - | Filter to specific contract |
limit | number | 50 | Maximum results to return |
offset | number | 0 | Number of results to skip |
Returns
Sale[] - Array of currently active sales (within start/end time window).