@w3lib/solana-batch-call 0.1.0 → 0.2.1
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/CHANGELOG.md +41 -0
- package/README.md +120 -18
- package/dist/address.d.ts +7 -1
- package/dist/address.d.ts.map +1 -1
- package/dist/address.js +56 -8
- package/dist/address.js.map +1 -1
- package/dist/client.d.ts +117 -23
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +756 -247
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +31 -2
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +68 -8
- package/dist/layout.js.map +1 -1
- package/dist/rpc.d.ts +65 -4
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +320 -42
- package/dist/rpc.js.map +1 -1
- package/dist/shortcuts.d.ts +38 -5
- package/dist/shortcuts.d.ts.map +1 -1
- package/dist/shortcuts.js +169 -12
- package/dist/shortcuts.js.map +1 -1
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +2 -4
- package/dist/source.js.map +1 -1
- package/dist/types.d.ts +54 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +13 -10
- package/src/address.ts +60 -8
- package/src/client.ts +974 -270
- package/src/index.ts +47 -3
- package/src/layout.ts +90 -8
- package/src/rpc.ts +368 -42
- package/src/shortcuts.ts +223 -16
- package/src/source.ts +2 -4
- package/src/types.ts +59 -3
package/src/address.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ed25519 } from '@noble/curves/ed25519.js'
|
|
2
1
|
import { sha256 } from '@noble/hashes/sha2.js'
|
|
3
2
|
import { base58 } from '@scure/base'
|
|
4
3
|
|
|
@@ -28,14 +27,57 @@ export function encodeAddress(bytes: Uint8Array): string {
|
|
|
28
27
|
return base58.encode(bytes)
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
// ed25519:-x² + y² = 1 + d·x²·y²(mod p)
|
|
31
|
+
const P = 2n ** 255n - 19n
|
|
32
|
+
const D = 37095705934669439343138083508754565189542113879843219016388785533085940283555n
|
|
33
|
+
|
|
34
|
+
/** x^(2^k) mod p */
|
|
35
|
+
function pow2k(x: bigint, k: number): bigint {
|
|
36
|
+
let r = x
|
|
37
|
+
for (let i = 0; i < k; i++) r = (r * r) % P
|
|
38
|
+
return r
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** x^((p-1)/2) mod p(欧拉判别法),(p-1)/2 = (2^250 - 1)·2^4 + 6,用加法链:约 254 次平方 + 12 次乘法 */
|
|
42
|
+
function legendre(x: bigint): bigint {
|
|
43
|
+
const b2 = (((x * x) % P) * x) % P // x^(2^2-1)
|
|
44
|
+
const b4 = (pow2k(b2, 2) * b2) % P
|
|
45
|
+
const b5 = (pow2k(b4, 1) * x) % P
|
|
46
|
+
const b10 = (pow2k(b5, 5) * b5) % P
|
|
47
|
+
const b20 = (pow2k(b10, 10) * b10) % P
|
|
48
|
+
const b40 = (pow2k(b20, 20) * b20) % P
|
|
49
|
+
const b80 = (pow2k(b40, 40) * b40) % P
|
|
50
|
+
const b160 = (pow2k(b80, 80) * b80) % P
|
|
51
|
+
const b240 = (pow2k(b160, 80) * b80) % P
|
|
52
|
+
const b250 = (pow2k(b240, 10) * b10) % P
|
|
53
|
+
return (pow2k(b250, 4) * ((b2 * b2) % P)) % P
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 32 字节是否是合法的 ed25519 压缩点(PDA 必须不在曲线上)。
|
|
58
|
+
* 按 RFC 8032 5.1.3 解压缩,与 @noble/curves 的 Point.fromBytes(web3.js 的 isOnCurve 同样如此)一致:
|
|
59
|
+
* y ≥ p、x = 0 但符号位为 1 都算不在曲线上。只需判断 x² = (y² - 1) / (d·y² + 1) 有没有解,不必真的开方
|
|
60
|
+
*/
|
|
61
|
+
export function isOnCurve(bytes: Uint8Array): boolean {
|
|
62
|
+
if (bytes.length !== 32) {
|
|
63
|
+
return false
|
|
64
|
+
}
|
|
65
|
+
let y = 0n
|
|
66
|
+
for (let i = 31; i >= 0; i--) {
|
|
67
|
+
y = (y << 8n) | BigInt(i === 31 ? (bytes[i] as number) & 0x7f : (bytes[i] as number))
|
|
68
|
+
}
|
|
69
|
+
if (y >= P) {
|
|
37
70
|
return false
|
|
38
71
|
}
|
|
72
|
+
const y2 = (y * y) % P
|
|
73
|
+
const u = (y2 - 1n + P) % P
|
|
74
|
+
const v = (D * y2 + 1n) % P // d 不是平方数,v 不会为 0
|
|
75
|
+
if (u === 0n) {
|
|
76
|
+
// x = 0:符号位必须为 0
|
|
77
|
+
return ((bytes[31] as number) & 0x80) === 0
|
|
78
|
+
}
|
|
79
|
+
// u / v 是平方数 ⇔ u·v 是平方数(欧拉判别法)
|
|
80
|
+
return legendre((u * v) % P) === 1n
|
|
39
81
|
}
|
|
40
82
|
|
|
41
83
|
const PDA_MARKER = new TextEncoder().encode('ProgramDerivedAddress')
|
|
@@ -50,14 +92,24 @@ function concat(parts: Uint8Array[]): Uint8Array {
|
|
|
50
92
|
return out
|
|
51
93
|
}
|
|
52
94
|
|
|
95
|
+
const MAX_SEED_LENGTH = 32
|
|
96
|
+
const MAX_SEEDS = 16
|
|
97
|
+
|
|
53
98
|
// PDA 推导是纯计算但要做多次 sha256 + 曲线判断,结果缓存
|
|
54
99
|
const pdaCache = new Map<string, string>()
|
|
55
100
|
|
|
56
101
|
/**
|
|
57
102
|
* 推导 PDA(与 web3.js PublicKey.findProgramAddressSync 相同),返回地址。
|
|
58
|
-
* seeds 每项不超过 32
|
|
103
|
+
* seeds 每项不超过 32 字节、最多 15 个(加上 bump 共 16 个,链上上限),超出时抛错。
|
|
59
104
|
*/
|
|
60
105
|
export function findProgramAddress(seeds: Uint8Array[], programId: string): string {
|
|
106
|
+
// 与链上和 web3.js 一致:每个种子最多 32 字节;种子加上 bump 最多 16 个
|
|
107
|
+
if (seeds.some((seed) => seed.length > MAX_SEED_LENGTH)) {
|
|
108
|
+
throw new TypeError('Max seed length exceeded')
|
|
109
|
+
}
|
|
110
|
+
if (seeds.length + 1 > MAX_SEEDS) {
|
|
111
|
+
throw new TypeError('Max seeds exceeded')
|
|
112
|
+
}
|
|
61
113
|
const key = `${programId}:${seeds.map((s) => encodeAddress(s)).join(',')}`
|
|
62
114
|
const cached = pdaCache.get(key)
|
|
63
115
|
if (cached) {
|