fix escrow handling and fetching
This commit is contained in:
@@ -7,7 +7,7 @@ export * from './listing'
|
||||
// Order exports are imported but we exclude the re-exported deriveEscrowId to avoid duplication
|
||||
// since it's already exported from pda.js
|
||||
export type { OrderAccountWithPda } from './order'
|
||||
export { fetchOrdersForListing, fetchOrdersByBuyer, fetchOrder } from './order'
|
||||
export { fetchOrdersForListing, fetchOrdersByBuyer, fetchOrderByEscrow, fetchOrder } from './order'
|
||||
|
||||
// Re-export Address for consumers
|
||||
export type { Address, Account } from '@solana/kit'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { address, type Account, type Address, type Rpc } from '@solana/kit'
|
||||
import { type GetProgramAccountsApi } from '@solana/rpc-api'
|
||||
import { type GetAccountInfoApi } from '@solana/rpc-api'
|
||||
import type { Base64EncodedBytes } from '@solana/rpc-types'
|
||||
import type { Base64EncodedBytes, Lamports } from '@solana/rpc-types'
|
||||
import {
|
||||
decodeSolistingStateOrderAccount,
|
||||
fetchSolistingStateOrderAccount,
|
||||
SOLISTING_STATE_ORDER_ACCOUNT_DISCRIMINATOR,
|
||||
getSolistingStateOrderAccountDiscriminatorBytes,
|
||||
type SolistingStateOrderAccount,
|
||||
} from './generated/solisting/src/generated/index'
|
||||
import { deriveEscrowId } from './pda'
|
||||
@@ -16,22 +16,57 @@ export type OrderAccountWithPda = Account<SolistingStateOrderAccount>
|
||||
type GpaRpc = Rpc<GetProgramAccountsApi>
|
||||
type GetRpc = Rpc<GetAccountInfoApi>
|
||||
|
||||
async function fetchAllOrders(rpc: GpaRpc): Promise<OrderAccountWithPda[]> {
|
||||
const disc = SOLISTING_STATE_ORDER_ACCOUNT_DISCRIMINATOR
|
||||
const discBase64 = Buffer.from(disc).toString('base64') as Base64EncodedBytes
|
||||
// OrderAccount byte layout (Sol-currency variant, the only one currently implemented):
|
||||
// 0: discriminator (8)
|
||||
// 8: listing (32)
|
||||
// 40: buyer (32)
|
||||
// 72: seller (32)
|
||||
// 104: resolver (32)
|
||||
// 136: paymentCurrency — Sol variant = 1 byte tag + 0 data = 1 byte total
|
||||
// 137: amount (8)
|
||||
// 145: escrowAccount (32)
|
||||
const LISTING_OFFSET = 8n
|
||||
const BUYER_OFFSET = 40n
|
||||
// escrowAccount offset is only valid for Sol-currency orders.
|
||||
// SPL orders (currently rejected by the program with SplNotImplemented) would sit at offset 178.
|
||||
const ESCROW_ACCOUNT_OFFSET = 145n
|
||||
|
||||
type RawGpaResult = Array<{
|
||||
pubkey: Address
|
||||
account: {
|
||||
executable: boolean
|
||||
lamports: bigint
|
||||
owner: Address
|
||||
space: bigint
|
||||
data: [string, 'base64']
|
||||
}
|
||||
}>
|
||||
|
||||
const DISC_BASE64 = Buffer.from(
|
||||
getSolistingStateOrderAccountDiscriminatorBytes(),
|
||||
).toString('base64') as Base64EncodedBytes
|
||||
|
||||
async function gpa(
|
||||
rpc: GpaRpc,
|
||||
addressFilter: { offset: bigint; addr: Address },
|
||||
): Promise<OrderAccountWithPda[]> {
|
||||
const results = await rpc
|
||||
.getProgramAccounts(PROGRAM_ADDRESS, {
|
||||
encoding: 'base64',
|
||||
filters: [{ memcmp: { offset: 0n, bytes: discBase64, encoding: 'base64' } }],
|
||||
filters: [
|
||||
{ memcmp: { offset: 0n, bytes: DISC_BASE64, encoding: 'base64' } },
|
||||
{ memcmp: { offset: addressFilter.offset, bytes: addressFilter.addr as never, encoding: 'base58' } },
|
||||
],
|
||||
})
|
||||
.send()
|
||||
return (results as Array<{ pubkey: Address; account: { executable: boolean; lamports: bigint; owner: Address; space: bigint; data: [string, 'base64'] } }>).map((r) => {
|
||||
|
||||
return (results as RawGpaResult).map((r) => {
|
||||
const data = new Uint8Array(Buffer.from(r.account.data[0], 'base64'))
|
||||
return decodeSolistingStateOrderAccount({
|
||||
address: r.pubkey,
|
||||
data,
|
||||
executable: r.account.executable,
|
||||
lamports: r.account.lamports as unknown as import('@solana/rpc-types').Lamports,
|
||||
lamports: r.account.lamports as unknown as Lamports,
|
||||
programAddress: r.account.owner,
|
||||
space: r.account.space,
|
||||
exists: true,
|
||||
@@ -39,26 +74,20 @@ async function fetchAllOrders(rpc: GpaRpc): Promise<OrderAccountWithPda[]> {
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchOrdersForListing(
|
||||
rpc: GpaRpc,
|
||||
listingPk: Address,
|
||||
): Promise<OrderAccountWithPda[]> {
|
||||
const all = await fetchAllOrders(rpc)
|
||||
return all.filter((o) => o.data.listing === listingPk)
|
||||
export function fetchOrdersForListing(rpc: GpaRpc, listingPk: Address): Promise<OrderAccountWithPda[]> {
|
||||
return gpa(rpc, { offset: LISTING_OFFSET, addr: listingPk })
|
||||
}
|
||||
|
||||
export async function fetchOrdersByBuyer(
|
||||
rpc: GpaRpc,
|
||||
buyer: Address,
|
||||
): Promise<OrderAccountWithPda[]> {
|
||||
const all = await fetchAllOrders(rpc)
|
||||
return all.filter((o) => o.data.buyer === buyer)
|
||||
export function fetchOrdersByBuyer(rpc: GpaRpc, buyer: Address): Promise<OrderAccountWithPda[]> {
|
||||
return gpa(rpc, { offset: BUYER_OFFSET, addr: buyer })
|
||||
}
|
||||
|
||||
export async function fetchOrder(
|
||||
rpc: GetRpc,
|
||||
addr: Address,
|
||||
): Promise<OrderAccountWithPda | null> {
|
||||
export async function fetchOrderByEscrow(rpc: GpaRpc, escrowPda: Address): Promise<OrderAccountWithPda | null> {
|
||||
const results = await gpa(rpc, { offset: ESCROW_ACCOUNT_OFFSET, addr: escrowPda })
|
||||
return results[0] ?? null
|
||||
}
|
||||
|
||||
export async function fetchOrder(rpc: GetRpc, addr: Address): Promise<OrderAccountWithPda | null> {
|
||||
return fetchSolistingStateOrderAccount(rpc, addr).catch(() => null)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user