@oobe-protocol-labs/synapse-sap-sdk 0.6.2 → 0.7.0
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/constants/seeds.js +7 -0
- package/dist/cjs/constants/seeds.js.map +1 -1
- package/dist/cjs/core/client.js +42 -0
- package/dist/cjs/core/client.js.map +1 -1
- package/dist/cjs/events/geyser.js +295 -0
- package/dist/cjs/events/geyser.js.map +1 -0
- package/dist/cjs/idl/synapse_agent_sap.json +7545 -3501
- package/dist/cjs/index.js +28 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/modules/escrow-v2.js +241 -0
- package/dist/cjs/modules/escrow-v2.js.map +1 -0
- package/dist/cjs/modules/escrow.js +4 -0
- package/dist/cjs/modules/escrow.js.map +1 -1
- package/dist/cjs/modules/index.js +7 -1
- package/dist/cjs/modules/index.js.map +1 -1
- package/dist/cjs/modules/staking.js +94 -0
- package/dist/cjs/modules/staking.js.map +1 -0
- package/dist/cjs/modules/subscription.js +96 -0
- package/dist/cjs/modules/subscription.js.map +1 -0
- package/dist/cjs/pda/index.js +143 -1
- package/dist/cjs/pda/index.js.map +1 -1
- package/dist/cjs/postgres/sync.js +72 -4
- package/dist/cjs/postgres/sync.js.map +1 -1
- package/dist/cjs/registries/x402.js +88 -51
- package/dist/cjs/registries/x402.js.map +1 -1
- package/dist/cjs/types/enums.js +51 -1
- package/dist/cjs/types/enums.js.map +1 -1
- package/dist/cjs/types/index.js +4 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/instructions.js.map +1 -1
- package/dist/cjs/utils/escrow-validation.js +219 -0
- package/dist/cjs/utils/escrow-validation.js.map +1 -0
- package/dist/cjs/utils/index.js +12 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/merchant-validator.js +246 -0
- package/dist/cjs/utils/merchant-validator.js.map +1 -0
- package/dist/cjs/utils/x402-direct.js +231 -0
- package/dist/cjs/utils/x402-direct.js.map +1 -0
- package/dist/esm/constants/seeds.js +7 -0
- package/dist/esm/constants/seeds.js.map +1 -1
- package/dist/esm/core/client.js +42 -0
- package/dist/esm/core/client.js.map +1 -1
- package/dist/esm/events/geyser.js +258 -0
- package/dist/esm/events/geyser.js.map +1 -0
- package/dist/esm/idl/synapse_agent_sap.json +7545 -3501
- package/dist/esm/index.js +7 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/modules/escrow-v2.js +237 -0
- package/dist/esm/modules/escrow-v2.js.map +1 -0
- package/dist/esm/modules/escrow.js +4 -0
- package/dist/esm/modules/escrow.js.map +1 -1
- package/dist/esm/modules/index.js +3 -0
- package/dist/esm/modules/index.js.map +1 -1
- package/dist/esm/modules/staking.js +90 -0
- package/dist/esm/modules/staking.js.map +1 -0
- package/dist/esm/modules/subscription.js +92 -0
- package/dist/esm/modules/subscription.js.map +1 -0
- package/dist/esm/pda/index.js +135 -0
- package/dist/esm/pda/index.js.map +1 -1
- package/dist/esm/postgres/sync.js +72 -4
- package/dist/esm/postgres/sync.js.map +1 -1
- package/dist/esm/registries/x402.js +89 -52
- package/dist/esm/registries/x402.js.map +1 -1
- package/dist/esm/types/enums.js +50 -0
- package/dist/esm/types/enums.js.map +1 -1
- package/dist/esm/types/index.js +1 -1
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/instructions.js.map +1 -1
- package/dist/esm/utils/escrow-validation.js +212 -0
- package/dist/esm/utils/escrow-validation.js.map +1 -0
- package/dist/esm/utils/index.js +4 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/merchant-validator.js +241 -0
- package/dist/esm/utils/merchant-validator.js.map +1 -0
- package/dist/esm/utils/x402-direct.js +228 -0
- package/dist/esm/utils/x402-direct.js.map +1 -0
- package/dist/types/constants/seeds.d.ts +7 -0
- package/dist/types/constants/seeds.d.ts.map +1 -1
- package/dist/types/core/client.d.ts +33 -0
- package/dist/types/core/client.d.ts.map +1 -1
- package/dist/types/events/geyser.d.ts +150 -0
- package/dist/types/events/geyser.d.ts.map +1 -0
- package/dist/types/index.d.ts +8 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modules/escrow-v2.d.ts +51 -0
- package/dist/types/modules/escrow-v2.d.ts.map +1 -0
- package/dist/types/modules/escrow.d.ts +4 -0
- package/dist/types/modules/escrow.d.ts.map +1 -1
- package/dist/types/modules/index.d.ts +3 -0
- package/dist/types/modules/index.d.ts.map +1 -1
- package/dist/types/modules/staking.d.ts +32 -0
- package/dist/types/modules/staking.d.ts.map +1 -0
- package/dist/types/modules/subscription.d.ts +33 -0
- package/dist/types/modules/subscription.d.ts.map +1 -0
- package/dist/types/pda/index.d.ts +99 -0
- package/dist/types/pda/index.d.ts.map +1 -1
- package/dist/types/plugin/schemas.d.ts +2 -2
- package/dist/types/postgres/sync.d.ts +26 -2
- package/dist/types/postgres/sync.d.ts.map +1 -1
- package/dist/types/registries/x402.d.ts +14 -12
- package/dist/types/registries/x402.d.ts.map +1 -1
- package/dist/types/types/accounts.d.ts +157 -1
- package/dist/types/types/accounts.d.ts.map +1 -1
- package/dist/types/types/enums.d.ts +64 -0
- package/dist/types/types/enums.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +4 -4
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/types/instructions.d.ts +34 -0
- package/dist/types/types/instructions.d.ts.map +1 -1
- package/dist/types/utils/escrow-validation.d.ts +145 -0
- package/dist/types/utils/escrow-validation.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +6 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/merchant-validator.d.ts +176 -0
- package/dist/types/utils/merchant-validator.d.ts.map +1 -0
- package/dist/types/utils/x402-direct.d.ts +114 -0
- package/dist/types/utils/x402-direct.d.ts.map +1 -0
- package/package.json +5 -1
- package/src/constants/seeds.ts +7 -0
- package/src/core/client.ts +45 -0
- package/src/events/geyser.ts +384 -0
- package/src/events/yellowstone.d.ts +7 -0
- package/src/idl/synapse_agent_sap.json +7545 -3501
- package/src/index.ts +51 -0
- package/src/modules/escrow-v2.ts +396 -0
- package/src/modules/escrow.ts +4 -0
- package/src/modules/index.ts +3 -0
- package/src/modules/staking.ts +122 -0
- package/src/modules/subscription.ts +147 -0
- package/src/pda/index.ts +196 -0
- package/src/postgres/sync.ts +90 -4
- package/src/registries/x402.ts +108 -69
- package/src/types/accounts.ts +192 -1
- package/src/types/enums.ts +65 -0
- package/src/types/index.ts +15 -0
- package/src/types/instructions.ts +40 -0
- package/src/utils/escrow-validation.ts +301 -0
- package/src/utils/index.ts +28 -0
- package/src/utils/merchant-validator.ts +359 -0
- package/src/utils/x402-direct.ts +370 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module subscription
|
|
3
|
+
* @description Agent subscription lifecycle — create, fund, cancel,
|
|
4
|
+
* close, and fetch subscription accounts.
|
|
5
|
+
*
|
|
6
|
+
* @category Modules
|
|
7
|
+
* @since v0.7.0
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
SystemProgram,
|
|
13
|
+
type PublicKey,
|
|
14
|
+
type TransactionSignature,
|
|
15
|
+
} from "@solana/web3.js";
|
|
16
|
+
import { BN } from "@coral-xyz/anchor";
|
|
17
|
+
import { BaseModule } from "./base";
|
|
18
|
+
import { deriveAgent, deriveSubscription } from "../pda";
|
|
19
|
+
import type { SubscriptionData, CreateSubscriptionArgs } from "../types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @name SubscriptionModule
|
|
23
|
+
* @description Manages recurring subscriptions between subscribers and agents.
|
|
24
|
+
*
|
|
25
|
+
* @category Modules
|
|
26
|
+
* @since v0.7.0
|
|
27
|
+
* @extends BaseModule
|
|
28
|
+
*/
|
|
29
|
+
export class SubscriptionModule extends BaseModule {
|
|
30
|
+
// ── PDA helpers ──────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
private toNum(v: BN | number | bigint): number {
|
|
33
|
+
return BN.isBN(v) ? v.toNumber() : Number(v);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
deriveSubscription(
|
|
37
|
+
agentPda: PublicKey,
|
|
38
|
+
subscriber?: PublicKey,
|
|
39
|
+
subId: BN | number | bigint = 0,
|
|
40
|
+
): readonly [PublicKey, number] {
|
|
41
|
+
return deriveSubscription(
|
|
42
|
+
agentPda,
|
|
43
|
+
subscriber ?? this.walletPubkey,
|
|
44
|
+
this.toNum(subId),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ── Instructions ─────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
async create(
|
|
51
|
+
agentWallet: PublicKey,
|
|
52
|
+
args: CreateSubscriptionArgs,
|
|
53
|
+
): Promise<TransactionSignature> {
|
|
54
|
+
const [agentPda] = deriveAgent(agentWallet);
|
|
55
|
+
const [subPda] = this.deriveSubscription(agentPda, undefined, args.subId);
|
|
56
|
+
|
|
57
|
+
return this.methods
|
|
58
|
+
.createSubscription(
|
|
59
|
+
this.bn(args.subId),
|
|
60
|
+
this.bn(args.pricePerInterval),
|
|
61
|
+
args.billingInterval,
|
|
62
|
+
this.bn(args.initialFund),
|
|
63
|
+
)
|
|
64
|
+
.accounts({
|
|
65
|
+
subscriber: this.walletPubkey,
|
|
66
|
+
agent: agentPda,
|
|
67
|
+
subscription: subPda,
|
|
68
|
+
systemProgram: SystemProgram.programId,
|
|
69
|
+
})
|
|
70
|
+
.rpc();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async fund(
|
|
74
|
+
agentWallet: PublicKey,
|
|
75
|
+
subId: BN | number | bigint,
|
|
76
|
+
amount: BN | number | bigint,
|
|
77
|
+
): Promise<TransactionSignature> {
|
|
78
|
+
const [agentPda] = deriveAgent(agentWallet);
|
|
79
|
+
const [subPda] = this.deriveSubscription(agentPda, undefined, subId);
|
|
80
|
+
|
|
81
|
+
return this.methods
|
|
82
|
+
.fundSubscription(this.bn(amount))
|
|
83
|
+
.accounts({
|
|
84
|
+
subscriber: this.walletPubkey,
|
|
85
|
+
subscription: subPda,
|
|
86
|
+
systemProgram: SystemProgram.programId,
|
|
87
|
+
})
|
|
88
|
+
.rpc();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async cancel(
|
|
92
|
+
agentWallet: PublicKey,
|
|
93
|
+
subId: BN | number | bigint = 0,
|
|
94
|
+
): Promise<TransactionSignature> {
|
|
95
|
+
const [agentPda] = deriveAgent(agentWallet);
|
|
96
|
+
const [subPda] = this.deriveSubscription(agentPda, undefined, subId);
|
|
97
|
+
|
|
98
|
+
return this.methods
|
|
99
|
+
.cancelSubscription()
|
|
100
|
+
.accounts({
|
|
101
|
+
subscriber: this.walletPubkey,
|
|
102
|
+
agentWallet,
|
|
103
|
+
subscription: subPda,
|
|
104
|
+
})
|
|
105
|
+
.rpc();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async close(
|
|
109
|
+
agentWallet: PublicKey,
|
|
110
|
+
subId: BN | number | bigint = 0,
|
|
111
|
+
): Promise<TransactionSignature> {
|
|
112
|
+
const [agentPda] = deriveAgent(agentWallet);
|
|
113
|
+
const [subPda] = this.deriveSubscription(agentPda, undefined, subId);
|
|
114
|
+
|
|
115
|
+
return this.methods
|
|
116
|
+
.closeSubscription()
|
|
117
|
+
.accounts({
|
|
118
|
+
subscriber: this.walletPubkey,
|
|
119
|
+
subscription: subPda,
|
|
120
|
+
})
|
|
121
|
+
.rpc();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ── Fetchers ─────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
async fetch(
|
|
127
|
+
agentPda: PublicKey,
|
|
128
|
+
subscriber?: PublicKey,
|
|
129
|
+
subId: BN | number | bigint = 0,
|
|
130
|
+
): Promise<SubscriptionData> {
|
|
131
|
+
const [pda] = this.deriveSubscription(agentPda, subscriber, subId);
|
|
132
|
+
return this.fetchAccount<SubscriptionData>("subscriptionAccount", pda);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async fetchNullable(
|
|
136
|
+
agentPda: PublicKey,
|
|
137
|
+
subscriber?: PublicKey,
|
|
138
|
+
subId: BN | number | bigint = 0,
|
|
139
|
+
): Promise<SubscriptionData | null> {
|
|
140
|
+
const [pda] = this.deriveSubscription(agentPda, subscriber, subId);
|
|
141
|
+
return this.fetchAccountNullable<SubscriptionData>("subscriptionAccount", pda);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async fetchByPda(subPda: PublicKey): Promise<SubscriptionData> {
|
|
145
|
+
return this.fetchAccount<SubscriptionData>("subscriptionAccount", subPda);
|
|
146
|
+
}
|
|
147
|
+
}
|
package/src/pda/index.ts
CHANGED
|
@@ -79,6 +79,22 @@ const u32le = (n: number): Buffer => {
|
|
|
79
79
|
return buf;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Encode an unsigned 64-bit integer as a little-endian `Buffer`.
|
|
84
|
+
*
|
|
85
|
+
* @name u64le
|
|
86
|
+
* @description Produces an 8-byte LE buffer for u64 PDA seed segments (e.g., escrow nonce, sub_id).
|
|
87
|
+
* @param n - The number or bigint to encode.
|
|
88
|
+
* @returns {Buffer} 8-byte little-endian buffer.
|
|
89
|
+
* @category PDA
|
|
90
|
+
* @since v0.5.0
|
|
91
|
+
*/
|
|
92
|
+
const u64le = (n: number | bigint): Buffer => {
|
|
93
|
+
const buf = Buffer.alloc(8);
|
|
94
|
+
buf.writeBigUInt64LE(BigInt(n), 0);
|
|
95
|
+
return buf;
|
|
96
|
+
};
|
|
97
|
+
|
|
82
98
|
// ═════════════════════════════════════════════
|
|
83
99
|
// Core PDAs
|
|
84
100
|
// ═════════════════════════════════════════════
|
|
@@ -421,6 +437,7 @@ export const deriveTool = (
|
|
|
421
437
|
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
422
438
|
* @category PDA
|
|
423
439
|
* @since v0.1.0
|
|
440
|
+
* @deprecated Since v0.7.0 — Use {@link deriveEscrowV2} for V2 escrows with nonce support.
|
|
424
441
|
* @see EscrowAccount
|
|
425
442
|
*/
|
|
426
443
|
export const deriveEscrow = (
|
|
@@ -650,3 +667,182 @@ export const deriveMemoryChunk = (
|
|
|
650
667
|
],
|
|
651
668
|
programId,
|
|
652
669
|
);
|
|
670
|
+
|
|
671
|
+
// ═════════════════════════════════════════════
|
|
672
|
+
// Escrow V2
|
|
673
|
+
// ═════════════════════════════════════════════
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Derive the **EscrowAccountV2** PDA.
|
|
677
|
+
*
|
|
678
|
+
* Seeds: `["sap_escrow_v2", agent_pda, depositor_wallet, nonce_u64_le]`
|
|
679
|
+
*
|
|
680
|
+
* @name deriveEscrowV2
|
|
681
|
+
* @description Computes the V2 escrow PDA supporting nonce-based multi-escrow.
|
|
682
|
+
* @param agentPda - The agent's PDA.
|
|
683
|
+
* @param depositor - The depositor's wallet.
|
|
684
|
+
* @param nonce - Escrow nonce (u64) allowing multiple escrows per pair.
|
|
685
|
+
* @param programId - Override program ID.
|
|
686
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
687
|
+
* @category PDA
|
|
688
|
+
* @since v0.5.0
|
|
689
|
+
*/
|
|
690
|
+
export const deriveEscrowV2 = (
|
|
691
|
+
agentPda: PublicKey,
|
|
692
|
+
depositor: PublicKey,
|
|
693
|
+
nonce: number | bigint = 0,
|
|
694
|
+
programId = SAP_PROGRAM_ID,
|
|
695
|
+
): PdaResult =>
|
|
696
|
+
findPda(
|
|
697
|
+
[
|
|
698
|
+
toSeedBuf(SEEDS.ESCROW_V2),
|
|
699
|
+
agentPda.toBuffer(),
|
|
700
|
+
depositor.toBuffer(),
|
|
701
|
+
u64le(nonce),
|
|
702
|
+
],
|
|
703
|
+
programId,
|
|
704
|
+
);
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Derive the **PendingSettlement** PDA.
|
|
708
|
+
*
|
|
709
|
+
* Seeds: `["sap_pending", escrow_v2_pda, settlement_index_u64_le]`
|
|
710
|
+
*
|
|
711
|
+
* @name derivePendingSettlement
|
|
712
|
+
* @param escrowV2Pda - The parent V2 escrow PDA.
|
|
713
|
+
* @param settlementIndex - The monotonic settlement index (u64).
|
|
714
|
+
* @param programId - Override program ID.
|
|
715
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
716
|
+
* @category PDA
|
|
717
|
+
* @since v0.5.0
|
|
718
|
+
*/
|
|
719
|
+
export const derivePendingSettlement = (
|
|
720
|
+
escrowV2Pda: PublicKey,
|
|
721
|
+
settlementIndex: number | bigint,
|
|
722
|
+
programId = SAP_PROGRAM_ID,
|
|
723
|
+
): PdaResult =>
|
|
724
|
+
findPda(
|
|
725
|
+
[
|
|
726
|
+
toSeedBuf(SEEDS.PENDING),
|
|
727
|
+
escrowV2Pda.toBuffer(),
|
|
728
|
+
u64le(settlementIndex),
|
|
729
|
+
],
|
|
730
|
+
programId,
|
|
731
|
+
);
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Derive the **DisputeRecord** PDA.
|
|
735
|
+
*
|
|
736
|
+
* Seeds: `["sap_dispute", pending_settlement_pda]`
|
|
737
|
+
*
|
|
738
|
+
* @name deriveDispute
|
|
739
|
+
* @param pendingSettlementPda - The parent pending settlement PDA.
|
|
740
|
+
* @param programId - Override program ID.
|
|
741
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
742
|
+
* @category PDA
|
|
743
|
+
* @since v0.5.0
|
|
744
|
+
*/
|
|
745
|
+
export const deriveDispute = (
|
|
746
|
+
pendingSettlementPda: PublicKey,
|
|
747
|
+
programId = SAP_PROGRAM_ID,
|
|
748
|
+
): PdaResult =>
|
|
749
|
+
findPda(
|
|
750
|
+
[toSeedBuf(SEEDS.DISPUTE), pendingSettlementPda.toBuffer()],
|
|
751
|
+
programId,
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Derive the **AgentStake** PDA.
|
|
756
|
+
*
|
|
757
|
+
* Seeds: `["sap_stake", agent_pda]`
|
|
758
|
+
*
|
|
759
|
+
* @name deriveStake
|
|
760
|
+
* @param agentPda - The agent's PDA.
|
|
761
|
+
* @param programId - Override program ID.
|
|
762
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
763
|
+
* @category PDA
|
|
764
|
+
* @since v0.5.0
|
|
765
|
+
*/
|
|
766
|
+
export const deriveStake = (
|
|
767
|
+
agentPda: PublicKey,
|
|
768
|
+
programId = SAP_PROGRAM_ID,
|
|
769
|
+
): PdaResult =>
|
|
770
|
+
findPda([toSeedBuf(SEEDS.STAKE), agentPda.toBuffer()], programId);
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Derive the **Subscription** PDA.
|
|
774
|
+
*
|
|
775
|
+
* Seeds: `["sap_sub", agent_pda, subscriber_wallet, sub_id_u64_le]`
|
|
776
|
+
*
|
|
777
|
+
* @name deriveSubscription
|
|
778
|
+
* @param agentPda - The agent's PDA.
|
|
779
|
+
* @param subscriber - The subscriber's wallet.
|
|
780
|
+
* @param subId - Subscription ID (u64).
|
|
781
|
+
* @param programId - Override program ID.
|
|
782
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
783
|
+
* @category PDA
|
|
784
|
+
* @since v0.5.0
|
|
785
|
+
*/
|
|
786
|
+
export const deriveSubscription = (
|
|
787
|
+
agentPda: PublicKey,
|
|
788
|
+
subscriber: PublicKey,
|
|
789
|
+
subId: number | bigint = 0,
|
|
790
|
+
programId = SAP_PROGRAM_ID,
|
|
791
|
+
): PdaResult =>
|
|
792
|
+
findPda(
|
|
793
|
+
[
|
|
794
|
+
toSeedBuf(SEEDS.SUBSCRIPTION),
|
|
795
|
+
agentPda.toBuffer(),
|
|
796
|
+
subscriber.toBuffer(),
|
|
797
|
+
u64le(subId),
|
|
798
|
+
],
|
|
799
|
+
programId,
|
|
800
|
+
);
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Derive the **CounterShard** PDA.
|
|
804
|
+
*
|
|
805
|
+
* Seeds: `["sap_shard", shard_index_u8]`
|
|
806
|
+
*
|
|
807
|
+
* @name deriveShard
|
|
808
|
+
* @param shardIndex - The shard index (0–7).
|
|
809
|
+
* @param programId - Override program ID.
|
|
810
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
811
|
+
* @category PDA
|
|
812
|
+
* @since v0.5.0
|
|
813
|
+
*/
|
|
814
|
+
export const deriveShard = (
|
|
815
|
+
shardIndex: number,
|
|
816
|
+
programId = SAP_PROGRAM_ID,
|
|
817
|
+
): PdaResult =>
|
|
818
|
+
findPda(
|
|
819
|
+
[toSeedBuf(SEEDS.SHARD), Buffer.from([shardIndex])],
|
|
820
|
+
programId,
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Derive the **IndexPage** PDA.
|
|
825
|
+
*
|
|
826
|
+
* Seeds: `["sap_idx_page", parent_index_pda, page_index_u8]`
|
|
827
|
+
*
|
|
828
|
+
* @name deriveIndexPage
|
|
829
|
+
* @param parentIndexPda - The parent index PDA (CapabilityIndex, ProtocolIndex, etc.).
|
|
830
|
+
* @param pageIndex - The page index (0–255).
|
|
831
|
+
* @param programId - Override program ID.
|
|
832
|
+
* @returns {PdaResult} `[pda, bump]` tuple.
|
|
833
|
+
* @category PDA
|
|
834
|
+
* @since v0.5.0
|
|
835
|
+
*/
|
|
836
|
+
export const deriveIndexPage = (
|
|
837
|
+
parentIndexPda: PublicKey,
|
|
838
|
+
pageIndex: number,
|
|
839
|
+
programId = SAP_PROGRAM_ID,
|
|
840
|
+
): PdaResult =>
|
|
841
|
+
findPda(
|
|
842
|
+
[
|
|
843
|
+
toSeedBuf(SEEDS.INDEX_PAGE),
|
|
844
|
+
parentIndexPda.toBuffer(),
|
|
845
|
+
Buffer.from([pageIndex]),
|
|
846
|
+
],
|
|
847
|
+
programId,
|
|
848
|
+
);
|
package/src/postgres/sync.ts
CHANGED
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
import type { SapClient } from "../core/client";
|
|
37
37
|
import { EventParser } from "../events";
|
|
38
|
+
import { GeyserEventStream, type GeyserConfig } from "../events/geyser";
|
|
38
39
|
import type { SapPostgres, SyncAllResult } from "./adapter";
|
|
39
40
|
import type { SyncOptions } from "./types";
|
|
40
41
|
|
|
@@ -67,6 +68,7 @@ export class SapSyncEngine {
|
|
|
67
68
|
|
|
68
69
|
private intervalId: ReturnType<typeof setInterval> | null = null;
|
|
69
70
|
private logSubId: number | null = null;
|
|
71
|
+
private geyserStream: GeyserEventStream | null = null;
|
|
70
72
|
private running = false;
|
|
71
73
|
|
|
72
74
|
constructor(pg: SapPostgres, client: SapClient, debug = false) {
|
|
@@ -208,7 +210,7 @@ export class SapSyncEngine {
|
|
|
208
210
|
|
|
209
211
|
/**
|
|
210
212
|
* @name stopEventStream
|
|
211
|
-
* @description Unsubscribe from the program log stream.
|
|
213
|
+
* @description Unsubscribe from the program log stream (WebSocket or Geyser).
|
|
212
214
|
* @since v0.1.0
|
|
213
215
|
*/
|
|
214
216
|
async stopEventStream(): Promise<void> {
|
|
@@ -216,8 +218,92 @@ export class SapSyncEngine {
|
|
|
216
218
|
const connection = this.client.program.provider.connection;
|
|
217
219
|
await connection.removeOnLogsListener(this.logSubId);
|
|
218
220
|
this.logSubId = null;
|
|
219
|
-
this.log("
|
|
221
|
+
this.log("WebSocket event stream stopped");
|
|
220
222
|
}
|
|
223
|
+
if (this.geyserStream) {
|
|
224
|
+
await this.geyserStream.disconnect();
|
|
225
|
+
this.geyserStream = null;
|
|
226
|
+
this.log("Geyser event stream stopped");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ═════════════════════════════════════════════
|
|
231
|
+
// Geyser gRPC Event Stream
|
|
232
|
+
// ═════════════════════════════════════════════
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @name startGeyserStream
|
|
236
|
+
* @description Subscribe to SAP program transactions via Yellowstone gRPC
|
|
237
|
+
* and insert parsed events into the `sap_events` table in real-time.
|
|
238
|
+
*
|
|
239
|
+
* Drop-in replacement for {@link startEventStream} with lower latency,
|
|
240
|
+
* no missed events, and automatic reconnection.
|
|
241
|
+
*
|
|
242
|
+
* Requires `@triton-one/yellowstone-grpc` to be installed.
|
|
243
|
+
*
|
|
244
|
+
* @param geyserConfig - Yellowstone gRPC connection config.
|
|
245
|
+
* @since v0.6.3
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```ts
|
|
249
|
+
* await sync.startGeyserStream({
|
|
250
|
+
* endpoint: "https://grpc.triton.one",
|
|
251
|
+
* token: process.env.GEYSER_TOKEN!,
|
|
252
|
+
* });
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
async startGeyserStream(geyserConfig: GeyserConfig): Promise<void> {
|
|
256
|
+
if (this.geyserStream) {
|
|
257
|
+
this.log("Geyser stream already running");
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const eventParser = new EventParser(this.client.program);
|
|
262
|
+
const stream = new GeyserEventStream(geyserConfig);
|
|
263
|
+
|
|
264
|
+
stream.on("logs", async (logs: string[], signature: string, slot: number) => {
|
|
265
|
+
try {
|
|
266
|
+
const events = eventParser.parseLogs(logs);
|
|
267
|
+
for (const event of events) {
|
|
268
|
+
const data = event.data as Record<string, unknown>;
|
|
269
|
+
const agentPda =
|
|
270
|
+
(data.agent as string) ?? (data.agentPda as string) ?? undefined;
|
|
271
|
+
const wallet =
|
|
272
|
+
(data.wallet as string) ?? (data.owner as string) ?? undefined;
|
|
273
|
+
|
|
274
|
+
await this.pg.syncEvent(
|
|
275
|
+
event.name,
|
|
276
|
+
signature,
|
|
277
|
+
slot,
|
|
278
|
+
data,
|
|
279
|
+
agentPda,
|
|
280
|
+
wallet,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
} catch (err) {
|
|
284
|
+
this.log(`Geyser event parse error: ${err}`);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
stream.on("connected", () => {
|
|
289
|
+
this.log("Geyser gRPC connected");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
stream.on("disconnected", (reason: string) => {
|
|
293
|
+
this.log(`Geyser gRPC disconnected: ${reason}`);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
stream.on("error", (err: Error) => {
|
|
297
|
+
this.log(`Geyser error: ${err.message}`);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
stream.on("reconnecting", (attempt: number) => {
|
|
301
|
+
this.log(`Geyser reconnecting (attempt ${attempt})...`);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
await stream.connect();
|
|
305
|
+
this.geyserStream = stream;
|
|
306
|
+
this.log("Geyser event stream started");
|
|
221
307
|
}
|
|
222
308
|
|
|
223
309
|
// ═════════════════════════════════════════════
|
|
@@ -235,11 +321,11 @@ export class SapSyncEngine {
|
|
|
235
321
|
|
|
236
322
|
/**
|
|
237
323
|
* @name isStreaming
|
|
238
|
-
* @description Check whether the event stream is active.
|
|
324
|
+
* @description Check whether the event stream is active (WebSocket or Geyser).
|
|
239
325
|
* @since v0.1.0
|
|
240
326
|
*/
|
|
241
327
|
isStreaming(): boolean {
|
|
242
|
-
return this.logSubId !== null;
|
|
328
|
+
return this.logSubId !== null || this.geyserStream?.connected === true;
|
|
243
329
|
}
|
|
244
330
|
|
|
245
331
|
// ═════════════════════════════════════════════
|