nara-sdk 1.0.88 → 1.0.90

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/index.ts CHANGED
@@ -124,7 +124,9 @@ export {
124
124
  getAgentMemory,
125
125
  getConfig as getAgentRegistryConfig,
126
126
  setBio,
127
+ makeSetBioIx,
127
128
  setMetadata,
129
+ makeSetMetadataIx,
128
130
  uploadMemory,
129
131
  closeBuffer as closeAgentBuffer,
130
132
  transferAgentAuthority,
@@ -136,10 +138,12 @@ export {
136
138
  setReferral,
137
139
  // Agent index
138
140
  getAgentIndex,
141
+ listIndexesByAgent,
139
142
  registerAgentIndex,
140
143
  unregisterAgentIndex,
141
144
  makeRegisterAgentIndexIx,
142
145
  makeUnregisterAgentIndexIx,
146
+ computeIndexHash,
143
147
  // Twitter verification
144
148
  getAgentTwitter,
145
149
  getTweetVerify,
@@ -170,6 +174,7 @@ export {
170
174
  type AgentRecord,
171
175
  type AgentInfo,
172
176
  type AgentIndexInfo,
177
+ type ReverseIndexInfo,
173
178
  type AgentTwitterInfo,
174
179
  type TweetVerifyInfo,
175
180
  type TweetRecordInfo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nara-sdk",
3
- "version": "1.0.88",
3
+ "version": "1.0.90",
4
4
  "description": "SDK for the Nara chain (Solana-compatible)",
5
5
  "module": "index.ts",
6
6
  "main": "index.ts",
@@ -35,6 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@coral-xyz/anchor": "^0.32.1",
38
+ "@noble/hashes": "^1.5.0",
38
39
  "@solana/spl-token": "^0.4.14",
39
40
  "@solana/web3.js": "^1.98.4",
40
41
  "bn.js": "^5.2.2",
@@ -14,6 +14,7 @@ import * as anchor from "@coral-xyz/anchor";
14
14
  import { Program, AnchorProvider, Wallet } from "@coral-xyz/anchor";
15
15
  import BN from "bn.js";
16
16
  import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
17
+ import { blake3 } from "@noble/hashes/blake3";
17
18
  import bs58 from "bs58";
18
19
  import type { NaraAgentRegistry } from "./idls/nara_agent_registry";
19
20
  import { DEFAULT_AGENT_REGISTRY_PROGRAM_ID } from "./constants";
@@ -64,6 +65,14 @@ export interface AgentIndexInfo {
64
65
  createdAt: number;
65
66
  }
66
67
 
68
+ export interface ReverseIndexInfo {
69
+ /** Agent PDA that owns this reverse-index entry */
70
+ agent: PublicKey;
71
+ /** Index string registered for the agent (UTF-8, up to 128 bytes) */
72
+ index: string;
73
+ createdAt: number;
74
+ }
75
+
67
76
  export interface AgentTwitterInfo {
68
77
  agentId: string;
69
78
  status: number;
@@ -189,9 +198,30 @@ function getTreasuryPda(programId: PublicKey): PublicKey {
189
198
  return pda;
190
199
  }
191
200
 
192
- function getAgentIndexPda(programId: PublicKey, indexStr: string): PublicKey {
201
+ /**
202
+ * BLAKE3 of an index string. The chain uses this 32-byte hash both as a PDA
203
+ * seed (lifting the 32-byte raw-seed limit) and as an integrity check against
204
+ * the supplied `index_str` (errors with `AgentIndexHashMismatch` on mismatch).
205
+ */
206
+ export function computeIndexHash(indexStr: string): Buffer {
207
+ return Buffer.from(blake3(Buffer.from(indexStr, "utf8")));
208
+ }
209
+
210
+ function getAgentIndexPda(programId: PublicKey, indexHash: Buffer | Uint8Array): PublicKey {
193
211
  const [pda] = PublicKey.findProgramAddressSync(
194
- [Buffer.from("agent_index"), Buffer.from(indexStr)],
212
+ [Buffer.from("agent_index"), Buffer.from(indexHash)],
213
+ programId
214
+ );
215
+ return pda;
216
+ }
217
+
218
+ function getReverseIndexPda(
219
+ programId: PublicKey,
220
+ agentPda: PublicKey,
221
+ indexHash: Buffer | Uint8Array
222
+ ): PublicKey {
223
+ const [pda] = PublicKey.findProgramAddressSync(
224
+ [Buffer.from("reverse_index"), agentPda.toBytes(), Buffer.from(indexHash)],
195
225
  programId
196
226
  );
197
227
  return pda;
@@ -729,6 +759,23 @@ export async function deleteAgent(
729
759
 
730
760
  // ─── Bio & Metadata ─────────────────────────────────────────────
731
761
 
762
+ /**
763
+ * Build a setBio instruction without sending it.
764
+ */
765
+ export async function makeSetBioIx(
766
+ connection: Connection,
767
+ authority: PublicKey,
768
+ agentId: string,
769
+ bio: string,
770
+ options?: AgentRegistryOptions
771
+ ): Promise<TransactionInstruction> {
772
+ const program = createProgram(connection, Keypair.generate(), options?.programId);
773
+ return program.methods
774
+ .setBio(agentId, bio)
775
+ .accounts({ authority } as any)
776
+ .instruction();
777
+ }
778
+
732
779
  /**
733
780
  * Set or update the agent's bio.
734
781
  */
@@ -739,14 +786,27 @@ export async function setBio(
739
786
  bio: string,
740
787
  options?: AgentRegistryOptions
741
788
  ): Promise<string> {
742
- const program = createProgram(connection, wallet, options?.programId);
743
- const ix = await program.methods
744
- .setBio(agentId, bio)
745
- .accounts({ authority: wallet.publicKey } as any)
746
- .instruction();
789
+ const ix = await makeSetBioIx(connection, wallet.publicKey, agentId, bio, options);
747
790
  return sendTx(connection, wallet, [ix]);
748
791
  }
749
792
 
793
+ /**
794
+ * Build a setMetadata instruction without sending it.
795
+ */
796
+ export async function makeSetMetadataIx(
797
+ connection: Connection,
798
+ authority: PublicKey,
799
+ agentId: string,
800
+ data: string,
801
+ options?: AgentRegistryOptions
802
+ ): Promise<TransactionInstruction> {
803
+ const program = createProgram(connection, Keypair.generate(), options?.programId);
804
+ return program.methods
805
+ .setMetadata(agentId, data)
806
+ .accounts({ authority } as any)
807
+ .instruction();
808
+ }
809
+
750
810
  /**
751
811
  * Set or update the agent's metadata (typically JSON).
752
812
  */
@@ -757,11 +817,7 @@ export async function setMetadata(
757
817
  data: string,
758
818
  options?: AgentRegistryOptions
759
819
  ): Promise<string> {
760
- const program = createProgram(connection, wallet, options?.programId);
761
- const ix = await program.methods
762
- .setMetadata(agentId, data)
763
- .accounts({ authority: wallet.publicKey } as any)
764
- .instruction();
820
+ const ix = await makeSetMetadataIx(connection, wallet.publicKey, agentId, data, options);
765
821
  return sendTx(connection, wallet, [ix]);
766
822
  }
767
823
 
@@ -1122,6 +1178,23 @@ function parseAgentIndexData(data: Buffer | Uint8Array): AgentIndexInfo {
1122
1178
  return { agent, agentId, createdAt };
1123
1179
  }
1124
1180
 
1181
+ /**
1182
+ * Parse ReverseIndex account data (bytemuck zero-copy layout).
1183
+ * Layout (after 8-byte discriminator):
1184
+ * 32 agent | 8 created_at | 4 index_len | 4 _padding |
1185
+ * 128 index | 32 _reserved
1186
+ */
1187
+ function parseReverseIndexData(data: Buffer | Uint8Array): ReverseIndexInfo {
1188
+ const buf = Buffer.from(data);
1189
+ let offset = 8;
1190
+ const agent = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
1191
+ const createdAt = Number(buf.readBigInt64LE(offset)); offset += 8;
1192
+ const indexLen = buf.readUInt32LE(offset); offset += 4;
1193
+ offset += 4; // _padding
1194
+ const index = buf.subarray(offset, offset + indexLen).toString("utf-8");
1195
+ return { agent, index, createdAt };
1196
+ }
1197
+
1125
1198
  /**
1126
1199
  * Look up an agent_index entry by index string.
1127
1200
  * Returns null if no agent has claimed this index.
@@ -1132,12 +1205,39 @@ export async function getAgentIndex(
1132
1205
  options?: AgentRegistryOptions
1133
1206
  ): Promise<AgentIndexInfo | null> {
1134
1207
  const pid = new PublicKey(options?.programId ?? DEFAULT_AGENT_REGISTRY_PROGRAM_ID);
1135
- const pda = getAgentIndexPda(pid, indexStr);
1208
+ const pda = getAgentIndexPda(pid, computeIndexHash(indexStr));
1136
1209
  const accountInfo = await connection.getAccountInfo(pda);
1137
1210
  if (!accountInfo) return null;
1138
1211
  return parseAgentIndexData(accountInfo.data);
1139
1212
  }
1140
1213
 
1214
+ /** ReverseIndex account discriminator (from IDL). */
1215
+ const REVERSE_INDEX_DISCRIMINATOR = Buffer.from([130, 180, 241, 155, 193, 32, 173, 207]);
1216
+
1217
+ /**
1218
+ * List all index strings registered for a given agent.
1219
+ * Scans the program via `getProgramAccounts` with memcmp filters on the
1220
+ * ReverseIndex discriminator and the `agent` field (offset 8).
1221
+ */
1222
+ export async function listIndexesByAgent(
1223
+ connection: Connection,
1224
+ agentId: string,
1225
+ options?: AgentRegistryOptions
1226
+ ): Promise<ReverseIndexInfo[]> {
1227
+ const pid = new PublicKey(options?.programId ?? DEFAULT_AGENT_REGISTRY_PROGRAM_ID);
1228
+ const agentPda = getAgentPda(pid, agentId);
1229
+
1230
+ const accounts = await connection.getProgramAccounts(pid, {
1231
+ commitment: "confirmed",
1232
+ filters: [
1233
+ { memcmp: { offset: 0, bytes: bs58.encode(REVERSE_INDEX_DISCRIMINATOR) } },
1234
+ { memcmp: { offset: 8, bytes: agentPda.toBase58() } },
1235
+ ],
1236
+ });
1237
+
1238
+ return accounts.map(({ account }) => parseReverseIndexData(account.data));
1239
+ }
1240
+
1141
1241
  /**
1142
1242
  * Build a registerAgentIndex instruction without sending it.
1143
1243
  */
@@ -1151,15 +1251,17 @@ export async function makeRegisterAgentIndexIx(
1151
1251
  ): Promise<TransactionInstruction> {
1152
1252
  const program = createProgram(connection, Keypair.generate(), options?.programId);
1153
1253
  const agent = getAgentPda(program.programId, agentId);
1254
+ const indexHash = computeIndexHash(indexStr);
1154
1255
  return program.methods
1155
- .registerAgentIndex(indexStr)
1256
+ .registerAgentIndex(indexStr, Array.from(indexHash))
1156
1257
  .accounts({ payer, authority, agent } as any)
1157
1258
  .instruction();
1158
1259
  }
1159
1260
 
1160
1261
  /**
1161
1262
  * Register a custom index string that points to the given agent.
1162
- * The (index_str → agent_id) mapping can be looked up via getAgentIndex.
1263
+ * The (index_str → agent_id) mapping can be looked up via getAgentIndex;
1264
+ * the reverse (agent → all index_strs) via listIndexesByAgent.
1163
1265
  */
1164
1266
  export async function registerAgentIndex(
1165
1267
  connection: Connection,
@@ -1168,12 +1270,13 @@ export async function registerAgentIndex(
1168
1270
  indexStr: string,
1169
1271
  options?: AgentRegistryOptions,
1170
1272
  payer?: Keypair
1171
- ): Promise<{ signature: string; agentIndexPda: PublicKey }> {
1273
+ ): Promise<{ signature: string; agentIndexPda: PublicKey; reverseIndexPda: PublicKey }> {
1172
1274
  const payerKp = payer ?? wallet;
1173
1275
  const program = createProgram(connection, payerKp, options?.programId);
1174
1276
  const agent = getAgentPda(program.programId, agentId);
1277
+ const indexHash = computeIndexHash(indexStr);
1175
1278
  const ix = await program.methods
1176
- .registerAgentIndex(indexStr)
1279
+ .registerAgentIndex(indexStr, Array.from(indexHash))
1177
1280
  .accounts({
1178
1281
  payer: payerKp.publicKey,
1179
1282
  authority: wallet.publicKey,
@@ -1182,7 +1285,11 @@ export async function registerAgentIndex(
1182
1285
  .instruction();
1183
1286
  const signers = payer && !payer.publicKey.equals(wallet.publicKey) ? [wallet] : [];
1184
1287
  const signature = await sendTx(connection, payerKp, [ix], signers);
1185
- return { signature, agentIndexPda: getAgentIndexPda(program.programId, indexStr) };
1288
+ return {
1289
+ signature,
1290
+ agentIndexPda: getAgentIndexPda(program.programId, indexHash),
1291
+ reverseIndexPda: getReverseIndexPda(program.programId, agent, indexHash),
1292
+ };
1186
1293
  }
1187
1294
 
1188
1295
  /**
@@ -1198,8 +1305,9 @@ export async function makeUnregisterAgentIndexIx(
1198
1305
  ): Promise<TransactionInstruction> {
1199
1306
  const program = createProgram(connection, Keypair.generate(), options?.programId);
1200
1307
  const agent = getAgentPda(program.programId, agentId);
1308
+ const indexHash = computeIndexHash(indexStr);
1201
1309
  return program.methods
1202
- .unregisterAgentIndex(indexStr)
1310
+ .unregisterAgentIndex(Array.from(indexHash))
1203
1311
  .accounts({ rentDestination, authority, agent } as any)
1204
1312
  .instruction();
1205
1313
  }
@@ -1219,8 +1327,9 @@ export async function unregisterAgentIndex(
1219
1327
  ): Promise<string> {
1220
1328
  const program = createProgram(connection, wallet, options?.programId);
1221
1329
  const agent = getAgentPda(program.programId, agentId);
1330
+ const indexHash = computeIndexHash(indexStr);
1222
1331
  const ix = await program.methods
1223
- .unregisterAgentIndex(indexStr)
1332
+ .unregisterAgentIndex(Array.from(indexHash))
1224
1333
  .accounts({
1225
1334
  rentDestination: rentDestination ?? wallet.publicKey,
1226
1335
  authority: wallet.publicKey,
@@ -1989,6 +1989,9 @@
1989
1989
  },
1990
1990
  {
1991
1991
  "name": "agent_index",
1992
+ "docs": [
1993
+ "Forward-lookup PDA: keyed by hash(index_str). Globally unique per index_str."
1994
+ ],
1992
1995
  "writable": true,
1993
1996
  "pda": {
1994
1997
  "seeds": [
@@ -2010,7 +2013,44 @@
2010
2013
  },
2011
2014
  {
2012
2015
  "kind": "arg",
2013
- "path": "index_str"
2016
+ "path": "index_hash"
2017
+ }
2018
+ ]
2019
+ }
2020
+ },
2021
+ {
2022
+ "name": "reverse_index",
2023
+ "docs": [
2024
+ "Reverse-lookup PDA: keyed by (agent, hash(index_str)). One per agent per index."
2025
+ ],
2026
+ "writable": true,
2027
+ "pda": {
2028
+ "seeds": [
2029
+ {
2030
+ "kind": "const",
2031
+ "value": [
2032
+ 114,
2033
+ 101,
2034
+ 118,
2035
+ 101,
2036
+ 114,
2037
+ 115,
2038
+ 101,
2039
+ 95,
2040
+ 105,
2041
+ 110,
2042
+ 100,
2043
+ 101,
2044
+ 120
2045
+ ]
2046
+ },
2047
+ {
2048
+ "kind": "account",
2049
+ "path": "agent"
2050
+ },
2051
+ {
2052
+ "kind": "arg",
2053
+ "path": "index_hash"
2014
2054
  }
2015
2055
  ]
2016
2056
  }
@@ -2024,6 +2064,15 @@
2024
2064
  {
2025
2065
  "name": "index_str",
2026
2066
  "type": "string"
2067
+ },
2068
+ {
2069
+ "name": "index_hash",
2070
+ "type": {
2071
+ "array": [
2072
+ "u8",
2073
+ 32
2074
+ ]
2075
+ }
2027
2076
  }
2028
2077
  ]
2029
2078
  },
@@ -3658,7 +3707,44 @@
3658
3707
  },
3659
3708
  {
3660
3709
  "kind": "arg",
3661
- "path": "index_str"
3710
+ "path": "index_hash"
3711
+ }
3712
+ ]
3713
+ }
3714
+ },
3715
+ {
3716
+ "name": "reverse_index",
3717
+ "docs": [
3718
+ "Reverse-lookup PDA, closed alongside the main index entry."
3719
+ ],
3720
+ "writable": true,
3721
+ "pda": {
3722
+ "seeds": [
3723
+ {
3724
+ "kind": "const",
3725
+ "value": [
3726
+ 114,
3727
+ 101,
3728
+ 118,
3729
+ 101,
3730
+ 114,
3731
+ 115,
3732
+ 101,
3733
+ 95,
3734
+ 105,
3735
+ 110,
3736
+ 100,
3737
+ 101,
3738
+ 120
3739
+ ]
3740
+ },
3741
+ {
3742
+ "kind": "account",
3743
+ "path": "agent"
3744
+ },
3745
+ {
3746
+ "kind": "arg",
3747
+ "path": "index_hash"
3662
3748
  }
3663
3749
  ]
3664
3750
  }
@@ -3670,8 +3756,13 @@
3670
3756
  ],
3671
3757
  "args": [
3672
3758
  {
3673
- "name": "index_str",
3674
- "type": "string"
3759
+ "name": "index_hash",
3760
+ "type": {
3761
+ "array": [
3762
+ "u8",
3763
+ 32
3764
+ ]
3765
+ }
3675
3766
  }
3676
3767
  ]
3677
3768
  },
@@ -4702,6 +4793,19 @@
4702
4793
  63
4703
4794
  ]
4704
4795
  },
4796
+ {
4797
+ "name": "ReverseIndex",
4798
+ "discriminator": [
4799
+ 130,
4800
+ 180,
4801
+ 241,
4802
+ 155,
4803
+ 193,
4804
+ 32,
4805
+ 173,
4806
+ 207
4807
+ ]
4808
+ },
4705
4809
  {
4706
4810
  "name": "TweetRecord",
4707
4811
  "discriminator": [
@@ -5038,6 +5142,11 @@
5038
5142
  "code": 6050,
5039
5143
  "name": "AgentIndexMismatch",
5040
5144
  "msg": "Agent index does not belong to the given agent"
5145
+ },
5146
+ {
5147
+ "code": 6051,
5148
+ "name": "AgentIndexHashMismatch",
5149
+ "msg": "Agent index hash does not match the provided index string"
5041
5150
  }
5042
5151
  ],
5043
5152
  "types": [
@@ -5479,6 +5588,71 @@
5479
5588
  ]
5480
5589
  }
5481
5590
  },
5591
+ {
5592
+ "name": "ReverseIndex",
5593
+ "docs": [
5594
+ "Reverse-lookup record: given an agent, list all index strings registered for it.",
5595
+ "Seeds: [SEED_REVERSE_INDEX, agent_pda.as_ref(), index_str.as_bytes()]",
5596
+ "",
5597
+ "Clients can fetch all reverse_index entries for a given agent via",
5598
+ "`getProgramAccounts` with a memcmp filter on the `agent` field."
5599
+ ],
5600
+ "serialization": "bytemuck",
5601
+ "repr": {
5602
+ "kind": "c"
5603
+ },
5604
+ "type": {
5605
+ "kind": "struct",
5606
+ "fields": [
5607
+ {
5608
+ "name": "agent",
5609
+ "docs": [
5610
+ "The AgentState PDA that owns this reverse-index entry"
5611
+ ],
5612
+ "type": "pubkey"
5613
+ },
5614
+ {
5615
+ "name": "created_at",
5616
+ "docs": [
5617
+ "Unix timestamp when this entry was created"
5618
+ ],
5619
+ "type": "i64"
5620
+ },
5621
+ {
5622
+ "name": "index_len",
5623
+ "docs": [
5624
+ "Length of the index string stored below"
5625
+ ],
5626
+ "type": "u32"
5627
+ },
5628
+ {
5629
+ "name": "_padding",
5630
+ "type": "u32"
5631
+ },
5632
+ {
5633
+ "name": "index",
5634
+ "docs": [
5635
+ "Index string (zero-padded), up to 128 bytes"
5636
+ ],
5637
+ "type": {
5638
+ "array": [
5639
+ "u8",
5640
+ 128
5641
+ ]
5642
+ }
5643
+ },
5644
+ {
5645
+ "name": "_reserved",
5646
+ "type": {
5647
+ "array": [
5648
+ "u8",
5649
+ 32
5650
+ ]
5651
+ }
5652
+ }
5653
+ ]
5654
+ }
5655
+ },
5482
5656
  {
5483
5657
  "name": "TweetRecord",
5484
5658
  "docs": [
@@ -1995,6 +1995,9 @@ export type NaraAgentRegistry = {
1995
1995
  },
1996
1996
  {
1997
1997
  "name": "agentIndex",
1998
+ "docs": [
1999
+ "Forward-lookup PDA: keyed by hash(index_str). Globally unique per index_str."
2000
+ ],
1998
2001
  "writable": true,
1999
2002
  "pda": {
2000
2003
  "seeds": [
@@ -2016,7 +2019,44 @@ export type NaraAgentRegistry = {
2016
2019
  },
2017
2020
  {
2018
2021
  "kind": "arg",
2019
- "path": "indexStr"
2022
+ "path": "indexHash"
2023
+ }
2024
+ ]
2025
+ }
2026
+ },
2027
+ {
2028
+ "name": "reverseIndex",
2029
+ "docs": [
2030
+ "Reverse-lookup PDA: keyed by (agent, hash(index_str)). One per agent per index."
2031
+ ],
2032
+ "writable": true,
2033
+ "pda": {
2034
+ "seeds": [
2035
+ {
2036
+ "kind": "const",
2037
+ "value": [
2038
+ 114,
2039
+ 101,
2040
+ 118,
2041
+ 101,
2042
+ 114,
2043
+ 115,
2044
+ 101,
2045
+ 95,
2046
+ 105,
2047
+ 110,
2048
+ 100,
2049
+ 101,
2050
+ 120
2051
+ ]
2052
+ },
2053
+ {
2054
+ "kind": "account",
2055
+ "path": "agent"
2056
+ },
2057
+ {
2058
+ "kind": "arg",
2059
+ "path": "indexHash"
2020
2060
  }
2021
2061
  ]
2022
2062
  }
@@ -2030,6 +2070,15 @@ export type NaraAgentRegistry = {
2030
2070
  {
2031
2071
  "name": "indexStr",
2032
2072
  "type": "string"
2073
+ },
2074
+ {
2075
+ "name": "indexHash",
2076
+ "type": {
2077
+ "array": [
2078
+ "u8",
2079
+ 32
2080
+ ]
2081
+ }
2033
2082
  }
2034
2083
  ]
2035
2084
  },
@@ -3664,7 +3713,44 @@ export type NaraAgentRegistry = {
3664
3713
  },
3665
3714
  {
3666
3715
  "kind": "arg",
3667
- "path": "indexStr"
3716
+ "path": "indexHash"
3717
+ }
3718
+ ]
3719
+ }
3720
+ },
3721
+ {
3722
+ "name": "reverseIndex",
3723
+ "docs": [
3724
+ "Reverse-lookup PDA, closed alongside the main index entry."
3725
+ ],
3726
+ "writable": true,
3727
+ "pda": {
3728
+ "seeds": [
3729
+ {
3730
+ "kind": "const",
3731
+ "value": [
3732
+ 114,
3733
+ 101,
3734
+ 118,
3735
+ 101,
3736
+ 114,
3737
+ 115,
3738
+ 101,
3739
+ 95,
3740
+ 105,
3741
+ 110,
3742
+ 100,
3743
+ 101,
3744
+ 120
3745
+ ]
3746
+ },
3747
+ {
3748
+ "kind": "account",
3749
+ "path": "agent"
3750
+ },
3751
+ {
3752
+ "kind": "arg",
3753
+ "path": "indexHash"
3668
3754
  }
3669
3755
  ]
3670
3756
  }
@@ -3676,8 +3762,13 @@ export type NaraAgentRegistry = {
3676
3762
  ],
3677
3763
  "args": [
3678
3764
  {
3679
- "name": "indexStr",
3680
- "type": "string"
3765
+ "name": "indexHash",
3766
+ "type": {
3767
+ "array": [
3768
+ "u8",
3769
+ 32
3770
+ ]
3771
+ }
3681
3772
  }
3682
3773
  ]
3683
3774
  },
@@ -4708,6 +4799,19 @@ export type NaraAgentRegistry = {
4708
4799
  63
4709
4800
  ]
4710
4801
  },
4802
+ {
4803
+ "name": "reverseIndex",
4804
+ "discriminator": [
4805
+ 130,
4806
+ 180,
4807
+ 241,
4808
+ 155,
4809
+ 193,
4810
+ 32,
4811
+ 173,
4812
+ 207
4813
+ ]
4814
+ },
4711
4815
  {
4712
4816
  "name": "tweetRecord",
4713
4817
  "discriminator": [
@@ -5044,6 +5148,11 @@ export type NaraAgentRegistry = {
5044
5148
  "code": 6050,
5045
5149
  "name": "agentIndexMismatch",
5046
5150
  "msg": "Agent index does not belong to the given agent"
5151
+ },
5152
+ {
5153
+ "code": 6051,
5154
+ "name": "agentIndexHashMismatch",
5155
+ "msg": "Agent index hash does not match the provided index string"
5047
5156
  }
5048
5157
  ],
5049
5158
  "types": [
@@ -5485,6 +5594,71 @@ export type NaraAgentRegistry = {
5485
5594
  ]
5486
5595
  }
5487
5596
  },
5597
+ {
5598
+ "name": "reverseIndex",
5599
+ "docs": [
5600
+ "Reverse-lookup record: given an agent, list all index strings registered for it.",
5601
+ "Seeds: [SEED_REVERSE_INDEX, agent_pda.as_ref(), index_str.as_bytes()]",
5602
+ "",
5603
+ "Clients can fetch all reverse_index entries for a given agent via",
5604
+ "`getProgramAccounts` with a memcmp filter on the `agent` field."
5605
+ ],
5606
+ "serialization": "bytemuck",
5607
+ "repr": {
5608
+ "kind": "c"
5609
+ },
5610
+ "type": {
5611
+ "kind": "struct",
5612
+ "fields": [
5613
+ {
5614
+ "name": "agent",
5615
+ "docs": [
5616
+ "The AgentState PDA that owns this reverse-index entry"
5617
+ ],
5618
+ "type": "pubkey"
5619
+ },
5620
+ {
5621
+ "name": "createdAt",
5622
+ "docs": [
5623
+ "Unix timestamp when this entry was created"
5624
+ ],
5625
+ "type": "i64"
5626
+ },
5627
+ {
5628
+ "name": "indexLen",
5629
+ "docs": [
5630
+ "Length of the index string stored below"
5631
+ ],
5632
+ "type": "u32"
5633
+ },
5634
+ {
5635
+ "name": "padding",
5636
+ "type": "u32"
5637
+ },
5638
+ {
5639
+ "name": "index",
5640
+ "docs": [
5641
+ "Index string (zero-padded), up to 128 bytes"
5642
+ ],
5643
+ "type": {
5644
+ "array": [
5645
+ "u8",
5646
+ 128
5647
+ ]
5648
+ }
5649
+ },
5650
+ {
5651
+ "name": "reserved",
5652
+ "type": {
5653
+ "array": [
5654
+ "u8",
5655
+ 32
5656
+ ]
5657
+ }
5658
+ }
5659
+ ]
5660
+ }
5661
+ },
5488
5662
  {
5489
5663
  "name": "tweetRecord",
5490
5664
  "docs": [