nara-sdk 1.0.62 → 1.0.63

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/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/nara-chain/nara-web/main/public/favicon.png" width="48" />
2
+ <img src="https://raw.githubusercontent.com/nara-chain/nara-web/main/public/favicon-v3.svg" width="48" />
3
3
  </p>
4
4
 
5
5
  <h3 align="center">Nara SDK</h3>
package/index.ts CHANGED
@@ -126,6 +126,7 @@ export {
126
126
  // Twitter verification
127
127
  getAgentTwitter,
128
128
  getTweetVerify,
129
+ getTweetRecord,
129
130
  getPendingTwitterVerifications,
130
131
  getPendingTweetVerifications,
131
132
  setTwitter,
@@ -152,6 +153,7 @@ export {
152
153
  type AgentInfo,
153
154
  type AgentTwitterInfo,
154
155
  type TweetVerifyInfo,
156
+ type TweetRecordInfo,
155
157
  type MemoryMode,
156
158
  type AgentRegistryOptions,
157
159
  } from "./src/agent_registry";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nara-sdk",
3
- "version": "1.0.62",
3
+ "version": "1.0.63",
4
4
  "description": "SDK for the Nara chain (Solana-compatible)",
5
5
  "module": "index.ts",
6
6
  "main": "index.ts",
@@ -65,7 +65,13 @@ export interface TweetVerifyInfo {
65
65
  status: number;
66
66
  submittedAt: number;
67
67
  lastRewardedAt: number;
68
- tweetUrl: string;
68
+ tweetId: bigint;
69
+ }
70
+
71
+ export interface TweetRecordInfo {
72
+ agent: PublicKey;
73
+ approvedAt: number;
74
+ tweetId: bigint;
69
75
  }
70
76
 
71
77
  export type MemoryMode = "new" | "update" | "append" | "auto";
@@ -295,9 +301,8 @@ function parseTweetVerifyData(data: Buffer | Uint8Array): TweetVerifyInfo {
295
301
  const status = Number(buf.readBigUInt64LE(offset)); offset += 8;
296
302
  const submittedAt = Number(buf.readBigInt64LE(offset)); offset += 8;
297
303
  const lastRewardedAt = Number(buf.readBigInt64LE(offset)); offset += 8;
298
- const tweetUrlLen = Number(buf.readBigUInt64LE(offset)); offset += 8;
299
- const tweetUrl = buf.subarray(offset, offset + tweetUrlLen).toString("utf-8");
300
- return { agentId, status, submittedAt, lastRewardedAt, tweetUrl };
304
+ const tweetId = buf.readBigUInt64LE(offset) | (buf.readBigUInt64LE(offset + 8) << 64n); offset += 16;
305
+ return { agentId, status, submittedAt, lastRewardedAt, tweetId };
301
306
  }
302
307
 
303
308
  /**
@@ -1214,6 +1219,34 @@ export async function getTweetVerify(
1214
1219
  return parseTweetVerifyData(accountInfo.data);
1215
1220
  }
1216
1221
 
1222
+ /**
1223
+ * Read a tweet record by tweet ID.
1224
+ * Returns null if no record exists.
1225
+ */
1226
+ export async function getTweetRecord(
1227
+ connection: Connection,
1228
+ tweetId: bigint,
1229
+ options?: AgentRegistryOptions
1230
+ ): Promise<TweetRecordInfo | null> {
1231
+ const pid = new PublicKey(options?.programId ?? DEFAULT_AGENT_REGISTRY_PROGRAM_ID);
1232
+ const tweetIdBuf = Buffer.alloc(16);
1233
+ tweetIdBuf.writeBigUInt64LE(tweetId & 0xFFFFFFFFFFFFFFFFn, 0);
1234
+ tweetIdBuf.writeBigUInt64LE(tweetId >> 64n, 8);
1235
+ const [pda] = PublicKey.findProgramAddressSync(
1236
+ [Buffer.from("tweet_record"), tweetIdBuf],
1237
+ pid
1238
+ );
1239
+ const accountInfo = await connection.getAccountInfo(pda);
1240
+ if (!accountInfo) return null;
1241
+
1242
+ const buf = Buffer.from(accountInfo.data);
1243
+ let offset = 8; // skip discriminator
1244
+ const agent = new PublicKey(buf.subarray(offset, offset + 32)); offset += 32;
1245
+ const approvedAt = Number(buf.readBigInt64LE(offset)); offset += 8;
1246
+ const recordTweetId = buf.readBigUInt64LE(offset) | (buf.readBigUInt64LE(offset + 8) << 64n);
1247
+ return { agent, approvedAt, tweetId: recordTweetId };
1248
+ }
1249
+
1217
1250
  /** Batch getMultipleAccountsInfo in chunks of 100 (RPC limit). */
1218
1251
  async function batchGetMultipleAccounts(
1219
1252
  connection: Connection,
@@ -1329,12 +1362,12 @@ export async function submitTweet(
1329
1362
  connection: Connection,
1330
1363
  wallet: Keypair,
1331
1364
  agentId: string,
1332
- tweetUrl: string,
1365
+ tweetId: bigint,
1333
1366
  options?: AgentRegistryOptions
1334
1367
  ): Promise<string> {
1335
1368
  const program = createProgram(connection, wallet, options?.programId);
1336
1369
  const ix = await program.methods
1337
- .submitTweet(agentId, tweetUrl)
1370
+ .submitTweet(agentId, new anchor.BN(tweetId.toString()))
1338
1371
  .accounts({ authority: wallet.publicKey } as any)
1339
1372
  .instruction();
1340
1373
  return sendTx(connection, wallet, [ix]);
@@ -1370,7 +1403,7 @@ export async function verifyTwitter(
1370
1403
  username: string,
1371
1404
  options?: AgentRegistryOptions,
1372
1405
  freeStakeDelta?: number,
1373
- tweetUrl?: string
1406
+ freeStakeReason?: string
1374
1407
  ): Promise<string> {
1375
1408
  const program = createProgram(connection, wallet, options?.programId);
1376
1409
  const agentPda = getAgentPda(program.programId, agentId);
@@ -1398,7 +1431,7 @@ export async function verifyTwitter(
1398
1431
  if (freeStakeDelta !== undefined && freeStakeDelta !== 0) {
1399
1432
  const { makeAdjustFreeStakeIx } = await import("./quest");
1400
1433
  const freeStakeIx = await makeAdjustFreeStakeIx(
1401
- connection, wallet.publicKey, authority, freeStakeDelta, tweetUrl ?? ""
1434
+ connection, wallet.publicKey, authority, freeStakeDelta, freeStakeReason ?? ""
1402
1435
  );
1403
1436
  ixs.push(freeStakeIx);
1404
1437
  }
@@ -1432,9 +1465,10 @@ export async function approveTweet(
1432
1465
  connection: Connection,
1433
1466
  wallet: Keypair,
1434
1467
  agentId: string,
1468
+ tweetId: bigint,
1435
1469
  options?: AgentRegistryOptions,
1436
1470
  freeStakeDelta?: number,
1437
- tweetUrl?: string
1471
+ freeStakeReason?: string
1438
1472
  ): Promise<string> {
1439
1473
  const program = createProgram(connection, wallet, options?.programId);
1440
1474
  const agentPda = getAgentPda(program.programId, agentId);
@@ -1450,7 +1484,7 @@ export async function approveTweet(
1450
1484
  );
1451
1485
 
1452
1486
  const ix = await program.methods
1453
- .approveTweet(agentId)
1487
+ .approveTweet(agentId, new anchor.BN(tweetId.toString()))
1454
1488
  .accounts({
1455
1489
  verifier: wallet.publicKey,
1456
1490
  authority,
@@ -1462,7 +1496,7 @@ export async function approveTweet(
1462
1496
  if (freeStakeDelta !== undefined && freeStakeDelta !== 0) {
1463
1497
  const { makeAdjustFreeStakeIx } = await import("./quest");
1464
1498
  const freeStakeIx = await makeAdjustFreeStakeIx(
1465
- connection, wallet.publicKey, authority, freeStakeDelta, tweetUrl ?? ""
1499
+ connection, wallet.publicKey, authority, freeStakeDelta, freeStakeReason ?? ""
1466
1500
  );
1467
1501
  ixs.push(freeStakeIx);
1468
1502
  }
@@ -93,6 +93,35 @@
93
93
  ]
94
94
  }
95
95
  },
96
+ {
97
+ "name": "tweet_record",
98
+ "writable": true,
99
+ "pda": {
100
+ "seeds": [
101
+ {
102
+ "kind": "const",
103
+ "value": [
104
+ 116,
105
+ 119,
106
+ 101,
107
+ 101,
108
+ 116,
109
+ 95,
110
+ 114,
111
+ 101,
112
+ 99,
113
+ 111,
114
+ 114,
115
+ 100
116
+ ]
117
+ },
118
+ {
119
+ "kind": "arg",
120
+ "path": "tweet_id"
121
+ }
122
+ ]
123
+ }
124
+ },
96
125
  {
97
126
  "name": "authority",
98
127
  "writable": true
@@ -305,6 +334,10 @@
305
334
  {
306
335
  "name": "agent_id",
307
336
  "type": "string"
337
+ },
338
+ {
339
+ "name": "tweet_id",
340
+ "type": "u128"
308
341
  }
309
342
  ]
310
343
  },
@@ -2804,6 +2837,34 @@
2804
2837
  ]
2805
2838
  }
2806
2839
  },
2840
+ {
2841
+ "name": "tweet_record",
2842
+ "pda": {
2843
+ "seeds": [
2844
+ {
2845
+ "kind": "const",
2846
+ "value": [
2847
+ 116,
2848
+ 119,
2849
+ 101,
2850
+ 101,
2851
+ 116,
2852
+ 95,
2853
+ 114,
2854
+ 101,
2855
+ 99,
2856
+ 111,
2857
+ 114,
2858
+ 100
2859
+ ]
2860
+ },
2861
+ {
2862
+ "kind": "arg",
2863
+ "path": "tweet_id"
2864
+ }
2865
+ ]
2866
+ }
2867
+ },
2807
2868
  {
2808
2869
  "name": "system_program",
2809
2870
  "address": "11111111111111111111111111111111"
@@ -2815,8 +2876,8 @@
2815
2876
  "type": "string"
2816
2877
  },
2817
2878
  {
2818
- "name": "tweet_url",
2819
- "type": "string"
2879
+ "name": "tweet_id",
2880
+ "type": "u128"
2820
2881
  }
2821
2882
  ]
2822
2883
  },
@@ -4040,6 +4101,19 @@
4040
4101
  63
4041
4102
  ]
4042
4103
  },
4104
+ {
4105
+ "name": "TweetRecord",
4106
+ "discriminator": [
4107
+ 13,
4108
+ 25,
4109
+ 5,
4110
+ 236,
4111
+ 64,
4112
+ 149,
4113
+ 72,
4114
+ 215
4115
+ ]
4116
+ },
4043
4117
  {
4044
4118
  "name": "TweetVerify",
4045
4119
  "discriminator": [
@@ -4302,6 +4376,16 @@
4302
4376
  "code": 6043,
4303
4377
  "name": "TwitterAlreadyVerified",
4304
4378
  "msg": "Twitter is already verified, unbind first"
4379
+ },
4380
+ {
4381
+ "code": 6044,
4382
+ "name": "InvalidTweetUrlFormat",
4383
+ "msg": "Invalid tweet URL format"
4384
+ },
4385
+ {
4386
+ "code": 6045,
4387
+ "name": "TweetAlreadyApproved",
4388
+ "msg": "Tweet has already been approved"
4305
4389
  }
4306
4390
  ],
4307
4391
  "types": [
@@ -4664,6 +4748,53 @@
4664
4748
  ]
4665
4749
  }
4666
4750
  },
4751
+ {
4752
+ "name": "TweetRecord",
4753
+ "docs": [
4754
+ "Records an approved tweet to prevent duplicate submissions.",
4755
+ "Seeds: [SEED_TWEET_RECORD, &tweet_id.to_le_bytes()]"
4756
+ ],
4757
+ "serialization": "bytemuck",
4758
+ "repr": {
4759
+ "kind": "c",
4760
+ "packed": true
4761
+ },
4762
+ "type": {
4763
+ "kind": "struct",
4764
+ "fields": [
4765
+ {
4766
+ "name": "agent",
4767
+ "docs": [
4768
+ "The agent PDA that submitted this tweet"
4769
+ ],
4770
+ "type": "pubkey"
4771
+ },
4772
+ {
4773
+ "name": "approved_at",
4774
+ "docs": [
4775
+ "Unix timestamp when this tweet was approved"
4776
+ ],
4777
+ "type": "i64"
4778
+ },
4779
+ {
4780
+ "name": "tweet_id",
4781
+ "docs": [
4782
+ "Tweet ID (Twitter snowflake ID)"
4783
+ ],
4784
+ "type": "u128"
4785
+ },
4786
+ {
4787
+ "name": "_reserved",
4788
+ "type": {
4789
+ "array": [
4790
+ "u8",
4791
+ 64
4792
+ ]
4793
+ }
4794
+ }
4795
+ ]
4796
+ }
4797
+ },
4667
4798
  {
4668
4799
  "name": "TweetVerify",
4669
4800
  "docs": [
@@ -4672,7 +4803,8 @@
4672
4803
  ],
4673
4804
  "serialization": "bytemuck",
4674
4805
  "repr": {
4675
- "kind": "c"
4806
+ "kind": "c",
4807
+ "packed": true
4676
4808
  },
4677
4809
  "type": {
4678
4810
  "kind": "struct",
@@ -4712,17 +4844,14 @@
4712
4844
  "type": "i64"
4713
4845
  },
4714
4846
  {
4715
- "name": "tweet_url_len",
4847
+ "name": "tweet_id",
4716
4848
  "docs": [
4717
- "Actual byte length of tweet_url"
4849
+ "Tweet ID (Twitter snowflake ID)"
4718
4850
  ],
4719
- "type": "u64"
4851
+ "type": "u128"
4720
4852
  },
4721
4853
  {
4722
- "name": "tweet_url",
4723
- "docs": [
4724
- "Tweet URL (max 256 bytes)"
4725
- ],
4854
+ "name": "_reserved",
4726
4855
  "type": {
4727
4856
  "array": [
4728
4857
  "u8",
@@ -4731,7 +4860,7 @@
4731
4860
  }
4732
4861
  },
4733
4862
  {
4734
- "name": "_reserved",
4863
+ "name": "_reserved2",
4735
4864
  "type": {
4736
4865
  "array": [
4737
4866
  "u8",
@@ -4740,11 +4869,38 @@
4740
4869
  }
4741
4870
  },
4742
4871
  {
4743
- "name": "_reserved2",
4872
+ "name": "_reserved3",
4744
4873
  "type": {
4745
4874
  "array": [
4746
4875
  "u8",
4747
- 128
4876
+ 64
4877
+ ]
4878
+ }
4879
+ },
4880
+ {
4881
+ "name": "_reserved4",
4882
+ "type": {
4883
+ "array": [
4884
+ "u8",
4885
+ 32
4886
+ ]
4887
+ }
4888
+ },
4889
+ {
4890
+ "name": "_reserved5",
4891
+ "type": {
4892
+ "array": [
4893
+ "u8",
4894
+ 16
4895
+ ]
4896
+ }
4897
+ },
4898
+ {
4899
+ "name": "_reserved6",
4900
+ "type": {
4901
+ "array": [
4902
+ "u8",
4903
+ 8
4748
4904
  ]
4749
4905
  }
4750
4906
  }
@@ -99,6 +99,35 @@ export type NaraAgentRegistry = {
99
99
  ]
100
100
  }
101
101
  },
102
+ {
103
+ "name": "tweetRecord",
104
+ "writable": true,
105
+ "pda": {
106
+ "seeds": [
107
+ {
108
+ "kind": "const",
109
+ "value": [
110
+ 116,
111
+ 119,
112
+ 101,
113
+ 101,
114
+ 116,
115
+ 95,
116
+ 114,
117
+ 101,
118
+ 99,
119
+ 111,
120
+ 114,
121
+ 100
122
+ ]
123
+ },
124
+ {
125
+ "kind": "arg",
126
+ "path": "tweetId"
127
+ }
128
+ ]
129
+ }
130
+ },
102
131
  {
103
132
  "name": "authority",
104
133
  "writable": true
@@ -311,6 +340,10 @@ export type NaraAgentRegistry = {
311
340
  {
312
341
  "name": "agentId",
313
342
  "type": "string"
343
+ },
344
+ {
345
+ "name": "tweetId",
346
+ "type": "u128"
314
347
  }
315
348
  ]
316
349
  },
@@ -2810,6 +2843,34 @@ export type NaraAgentRegistry = {
2810
2843
  ]
2811
2844
  }
2812
2845
  },
2846
+ {
2847
+ "name": "tweetRecord",
2848
+ "pda": {
2849
+ "seeds": [
2850
+ {
2851
+ "kind": "const",
2852
+ "value": [
2853
+ 116,
2854
+ 119,
2855
+ 101,
2856
+ 101,
2857
+ 116,
2858
+ 95,
2859
+ 114,
2860
+ 101,
2861
+ 99,
2862
+ 111,
2863
+ 114,
2864
+ 100
2865
+ ]
2866
+ },
2867
+ {
2868
+ "kind": "arg",
2869
+ "path": "tweetId"
2870
+ }
2871
+ ]
2872
+ }
2873
+ },
2813
2874
  {
2814
2875
  "name": "systemProgram",
2815
2876
  "address": "11111111111111111111111111111111"
@@ -2821,8 +2882,8 @@ export type NaraAgentRegistry = {
2821
2882
  "type": "string"
2822
2883
  },
2823
2884
  {
2824
- "name": "tweetUrl",
2825
- "type": "string"
2885
+ "name": "tweetId",
2886
+ "type": "u128"
2826
2887
  }
2827
2888
  ]
2828
2889
  },
@@ -4046,6 +4107,19 @@ export type NaraAgentRegistry = {
4046
4107
  63
4047
4108
  ]
4048
4109
  },
4110
+ {
4111
+ "name": "tweetRecord",
4112
+ "discriminator": [
4113
+ 13,
4114
+ 25,
4115
+ 5,
4116
+ 236,
4117
+ 64,
4118
+ 149,
4119
+ 72,
4120
+ 215
4121
+ ]
4122
+ },
4049
4123
  {
4050
4124
  "name": "tweetVerify",
4051
4125
  "discriminator": [
@@ -4308,6 +4382,16 @@ export type NaraAgentRegistry = {
4308
4382
  "code": 6043,
4309
4383
  "name": "twitterAlreadyVerified",
4310
4384
  "msg": "Twitter is already verified, unbind first"
4385
+ },
4386
+ {
4387
+ "code": 6044,
4388
+ "name": "invalidTweetUrlFormat",
4389
+ "msg": "Invalid tweet URL format"
4390
+ },
4391
+ {
4392
+ "code": 6045,
4393
+ "name": "tweetAlreadyApproved",
4394
+ "msg": "Tweet has already been approved"
4311
4395
  }
4312
4396
  ],
4313
4397
  "types": [
@@ -4670,6 +4754,53 @@ export type NaraAgentRegistry = {
4670
4754
  ]
4671
4755
  }
4672
4756
  },
4757
+ {
4758
+ "name": "tweetRecord",
4759
+ "docs": [
4760
+ "Records an approved tweet to prevent duplicate submissions.",
4761
+ "Seeds: [SEED_TWEET_RECORD, &tweet_id.to_le_bytes()]"
4762
+ ],
4763
+ "serialization": "bytemuck",
4764
+ "repr": {
4765
+ "kind": "c",
4766
+ "packed": true
4767
+ },
4768
+ "type": {
4769
+ "kind": "struct",
4770
+ "fields": [
4771
+ {
4772
+ "name": "agent",
4773
+ "docs": [
4774
+ "The agent PDA that submitted this tweet"
4775
+ ],
4776
+ "type": "pubkey"
4777
+ },
4778
+ {
4779
+ "name": "approvedAt",
4780
+ "docs": [
4781
+ "Unix timestamp when this tweet was approved"
4782
+ ],
4783
+ "type": "i64"
4784
+ },
4785
+ {
4786
+ "name": "tweetId",
4787
+ "docs": [
4788
+ "Tweet ID (Twitter snowflake ID)"
4789
+ ],
4790
+ "type": "u128"
4791
+ },
4792
+ {
4793
+ "name": "reserved",
4794
+ "type": {
4795
+ "array": [
4796
+ "u8",
4797
+ 64
4798
+ ]
4799
+ }
4800
+ }
4801
+ ]
4802
+ }
4803
+ },
4673
4804
  {
4674
4805
  "name": "tweetVerify",
4675
4806
  "docs": [
@@ -4678,7 +4809,8 @@ export type NaraAgentRegistry = {
4678
4809
  ],
4679
4810
  "serialization": "bytemuck",
4680
4811
  "repr": {
4681
- "kind": "c"
4812
+ "kind": "c",
4813
+ "packed": true
4682
4814
  },
4683
4815
  "type": {
4684
4816
  "kind": "struct",
@@ -4718,17 +4850,14 @@ export type NaraAgentRegistry = {
4718
4850
  "type": "i64"
4719
4851
  },
4720
4852
  {
4721
- "name": "tweetUrlLen",
4853
+ "name": "tweetId",
4722
4854
  "docs": [
4723
- "Actual byte length of tweet_url"
4855
+ "Tweet ID (Twitter snowflake ID)"
4724
4856
  ],
4725
- "type": "u64"
4857
+ "type": "u128"
4726
4858
  },
4727
4859
  {
4728
- "name": "tweetUrl",
4729
- "docs": [
4730
- "Tweet URL (max 256 bytes)"
4731
- ],
4860
+ "name": "reserved",
4732
4861
  "type": {
4733
4862
  "array": [
4734
4863
  "u8",
@@ -4737,7 +4866,7 @@ export type NaraAgentRegistry = {
4737
4866
  }
4738
4867
  },
4739
4868
  {
4740
- "name": "reserved",
4869
+ "name": "reserved2",
4741
4870
  "type": {
4742
4871
  "array": [
4743
4872
  "u8",
@@ -4746,11 +4875,38 @@ export type NaraAgentRegistry = {
4746
4875
  }
4747
4876
  },
4748
4877
  {
4749
- "name": "reserved2",
4878
+ "name": "reserved3",
4750
4879
  "type": {
4751
4880
  "array": [
4752
4881
  "u8",
4753
- 128
4882
+ 64
4883
+ ]
4884
+ }
4885
+ },
4886
+ {
4887
+ "name": "reserved4",
4888
+ "type": {
4889
+ "array": [
4890
+ "u8",
4891
+ 32
4892
+ ]
4893
+ }
4894
+ },
4895
+ {
4896
+ "name": "reserved5",
4897
+ "type": {
4898
+ "array": [
4899
+ "u8",
4900
+ 16
4901
+ ]
4902
+ }
4903
+ },
4904
+ {
4905
+ "name": "reserved6",
4906
+ "type": {
4907
+ "array": [
4908
+ "u8",
4909
+ 8
4754
4910
  ]
4755
4911
  }
4756
4912
  }