@exodus/solana-lib 1.2.13 → 1.2.14
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/lib/constants.js +19 -0
- package/lib/encode.js +67 -0
- package/lib/fee-data/index.js +15 -0
- package/lib/fee-data/solana.js +14 -0
- package/lib/helpers/spl-token.js +122 -0
- package/lib/helpers/tokenTransfer.js +78 -0
- package/lib/index.js +88 -0
- package/lib/keypair.js +38 -0
- package/lib/tokens.js +21 -0
- package/lib/transaction.js +338 -0
- package/lib/tx/create-and-sign-tx.js +15 -0
- package/{src → lib}/tx/create-unsigned-tx.js +18 -11
- package/lib/tx/index.js +53 -0
- package/lib/tx/parse-unsigned-tx.js +55 -0
- package/lib/tx/sign-unsigned-tx.js +90 -0
- package/lib/vendor/account.js +48 -0
- package/lib/vendor/index.js +113 -0
- package/lib/vendor/instruction.js +48 -0
- package/lib/vendor/message.js +167 -0
- package/lib/vendor/nonce-account.js +56 -0
- package/lib/vendor/publickey.js +211 -0
- package/lib/vendor/stake-program.js +476 -0
- package/lib/vendor/system-program.js +640 -0
- package/lib/vendor/sysvar.js +19 -0
- package/lib/vendor/transaction.js +594 -0
- package/lib/vendor/utils/blockhash.js +1 -0
- package/lib/vendor/utils/fee-calculator.js +25 -0
- package/lib/vendor/utils/layout.js +97 -0
- package/lib/vendor/utils/shortvec-encoding.js +41 -0
- package/lib/vendor/utils/to-buffer.js +18 -0
- package/package.json +4 -5
- package/src/constants.js +0 -12
- package/src/encode.js +0 -57
- package/src/fee-data/index.js +0 -1
- package/src/fee-data/solana.js +0 -9
- package/src/helpers/spl-token.js +0 -108
- package/src/helpers/tokenTransfer.js +0 -72
- package/src/index.js +0 -9
- package/src/keypair.js +0 -32
- package/src/tokens.js +0 -19
- package/src/transaction.js +0 -292
- package/src/tx/create-and-sign-tx.js +0 -8
- package/src/tx/index.js +0 -4
- package/src/tx/parse-unsigned-tx.js +0 -41
- package/src/tx/sign-unsigned-tx.js +0 -78
- package/src/vendor/account.js +0 -38
- package/src/vendor/index.js +0 -9
- package/src/vendor/instruction.js +0 -46
- package/src/vendor/message.js +0 -216
- package/src/vendor/nonce-account.js +0 -46
- package/src/vendor/publickey.js +0 -212
- package/src/vendor/stake-program.js +0 -527
- package/src/vendor/system-program.js +0 -782
- package/src/vendor/sysvar.js +0 -16
- package/src/vendor/transaction.js +0 -594
- package/src/vendor/utils/blockhash.js +0 -6
- package/src/vendor/utils/fee-calculator.js +0 -17
- package/src/vendor/utils/layout.js +0 -80
- package/src/vendor/utils/shortvec-encoding.js +0 -30
- package/src/vendor/utils/to-buffer.js +0 -9
package/src/vendor/message.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
|
|
3
|
-
import bs58 from 'bs58'
|
|
4
|
-
import * as BufferLayout from '@exodus/buffer-layout'
|
|
5
|
-
|
|
6
|
-
import { PublicKey } from './publickey'
|
|
7
|
-
import type { Blockhash } from './utils/blockhash'
|
|
8
|
-
import * as Layout from './utils/layout'
|
|
9
|
-
import { PACKET_DATA_SIZE } from './transaction'
|
|
10
|
-
import * as shortvec from './utils/shortvec-encoding'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The message header, identifying signed and read-only account
|
|
14
|
-
*
|
|
15
|
-
* @typedef {Object} MessageHeader
|
|
16
|
-
* @property {number} numRequiredSignatures The number of signatures required for this message to be considered valid. The
|
|
17
|
-
* signatures must match the first `numRequiredSignatures` of `accountKeys`.
|
|
18
|
-
* @property {number} numReadonlySignedAccounts: The last `numReadonlySignedAccounts` of the signed keys are read-only accounts
|
|
19
|
-
* @property {number} numReadonlyUnsignedAccounts The last `numReadonlySignedAccounts` of the unsigned keys are read-only accounts
|
|
20
|
-
*/
|
|
21
|
-
export type MessageHeader = {
|
|
22
|
-
numRequiredSignatures: number,
|
|
23
|
-
numReadonlySignedAccounts: number,
|
|
24
|
-
numReadonlyUnsignedAccounts: number,
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* An instruction to execute by a program
|
|
29
|
-
*
|
|
30
|
-
* @typedef {Object} CompiledInstruction
|
|
31
|
-
* @property {number} programIdIndex Index into the transaction keys array indicating the program account that executes this instruction
|
|
32
|
-
* @property {number[]} accounts Ordered indices into the transaction keys array indicating which accounts to pass to the program
|
|
33
|
-
* @property {string} data The program input data encoded as base 58
|
|
34
|
-
*/
|
|
35
|
-
export type CompiledInstruction = {
|
|
36
|
-
programIdIndex: number,
|
|
37
|
-
accounts: number[],
|
|
38
|
-
data: string,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Message constructor arguments
|
|
43
|
-
*
|
|
44
|
-
* @typedef {Object} MessageArgs
|
|
45
|
-
* @property {MessageHeader} header The message header, identifying signed and read-only `accountKeys`
|
|
46
|
-
* @property {string[]} accounts All the account keys used by this transaction
|
|
47
|
-
* @property {Blockhash} recentBlockhash The hash of a recent ledger block
|
|
48
|
-
* @property {CompiledInstruction[]} instructions Instructions that will be executed in sequence and committed in one atomic transaction if all succeed.
|
|
49
|
-
*/
|
|
50
|
-
type MessageArgs = {
|
|
51
|
-
header: MessageHeader,
|
|
52
|
-
accountKeys: string[],
|
|
53
|
-
recentBlockhash: Blockhash,
|
|
54
|
-
instructions: CompiledInstruction[],
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const PUBKEY_LENGTH = 32
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* List of instructions to be processed atomically
|
|
61
|
-
*/
|
|
62
|
-
export class Message {
|
|
63
|
-
header: MessageHeader
|
|
64
|
-
accountKeys: PublicKey[]
|
|
65
|
-
recentBlockhash: Blockhash
|
|
66
|
-
instructions: CompiledInstruction[]
|
|
67
|
-
|
|
68
|
-
constructor(args: MessageArgs) {
|
|
69
|
-
this.header = args.header
|
|
70
|
-
this.accountKeys = args.accountKeys.map((account) => new PublicKey(account))
|
|
71
|
-
this.recentBlockhash = args.recentBlockhash
|
|
72
|
-
this.instructions = args.instructions
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
isAccountWritable(index: number): boolean {
|
|
76
|
-
return (
|
|
77
|
-
index < this.header.numRequiredSignatures - this.header.numReadonlySignedAccounts ||
|
|
78
|
-
(index >= this.header.numRequiredSignatures &&
|
|
79
|
-
index < this.accountKeys.length - this.header.numReadonlyUnsignedAccounts)
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
findSignerIndex(signer: PublicKey): number {
|
|
84
|
-
const index = this.accountKeys.findIndex((accountKey) => {
|
|
85
|
-
return accountKey.equals(signer)
|
|
86
|
-
})
|
|
87
|
-
if (index < 0) {
|
|
88
|
-
throw new Error(`unknown signer: ${signer.toString()}`)
|
|
89
|
-
}
|
|
90
|
-
return index
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
serialize(): Buffer {
|
|
94
|
-
const numKeys = this.accountKeys.length
|
|
95
|
-
|
|
96
|
-
let keyCount = []
|
|
97
|
-
shortvec.encodeLength(keyCount, numKeys)
|
|
98
|
-
|
|
99
|
-
const instructions = this.instructions.map((instruction) => {
|
|
100
|
-
const { accounts, programIdIndex } = instruction
|
|
101
|
-
const data = bs58.decode(instruction.data)
|
|
102
|
-
|
|
103
|
-
let keyIndicesCount = []
|
|
104
|
-
shortvec.encodeLength(keyIndicesCount, accounts.length)
|
|
105
|
-
|
|
106
|
-
let dataCount = []
|
|
107
|
-
shortvec.encodeLength(dataCount, data.length)
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
programIdIndex,
|
|
111
|
-
keyIndicesCount: Buffer.from(keyIndicesCount),
|
|
112
|
-
keyIndices: Buffer.from(accounts),
|
|
113
|
-
dataLength: Buffer.from(dataCount),
|
|
114
|
-
data,
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
let instructionCount = []
|
|
119
|
-
shortvec.encodeLength(instructionCount, instructions.length)
|
|
120
|
-
let instructionBuffer = Buffer.alloc(PACKET_DATA_SIZE)
|
|
121
|
-
Buffer.from(instructionCount).copy(instructionBuffer)
|
|
122
|
-
let instructionBufferLength = instructionCount.length
|
|
123
|
-
|
|
124
|
-
instructions.forEach((instruction) => {
|
|
125
|
-
const instructionLayout = BufferLayout.struct([
|
|
126
|
-
BufferLayout.u8('programIdIndex'),
|
|
127
|
-
|
|
128
|
-
BufferLayout.blob(instruction.keyIndicesCount.length, 'keyIndicesCount'),
|
|
129
|
-
BufferLayout.seq(BufferLayout.u8('keyIndex'), instruction.keyIndices.length, 'keyIndices'),
|
|
130
|
-
BufferLayout.blob(instruction.dataLength.length, 'dataLength'),
|
|
131
|
-
BufferLayout.seq(BufferLayout.u8('userdatum'), instruction.data.length, 'data'),
|
|
132
|
-
])
|
|
133
|
-
const length = instructionLayout.encode(
|
|
134
|
-
instruction,
|
|
135
|
-
instructionBuffer,
|
|
136
|
-
instructionBufferLength
|
|
137
|
-
)
|
|
138
|
-
instructionBufferLength += length
|
|
139
|
-
})
|
|
140
|
-
instructionBuffer = instructionBuffer.slice(0, instructionBufferLength)
|
|
141
|
-
|
|
142
|
-
const signDataLayout = BufferLayout.struct([
|
|
143
|
-
BufferLayout.blob(1, 'numRequiredSignatures'),
|
|
144
|
-
BufferLayout.blob(1, 'numReadonlySignedAccounts'),
|
|
145
|
-
BufferLayout.blob(1, 'numReadonlyUnsignedAccounts'),
|
|
146
|
-
BufferLayout.blob(keyCount.length, 'keyCount'),
|
|
147
|
-
BufferLayout.seq(Layout.publicKey('key'), numKeys, 'keys'),
|
|
148
|
-
Layout.publicKey('recentBlockhash'),
|
|
149
|
-
])
|
|
150
|
-
|
|
151
|
-
const transaction = {
|
|
152
|
-
numRequiredSignatures: Buffer.from([this.header.numRequiredSignatures]),
|
|
153
|
-
numReadonlySignedAccounts: Buffer.from([this.header.numReadonlySignedAccounts]),
|
|
154
|
-
numReadonlyUnsignedAccounts: Buffer.from([this.header.numReadonlyUnsignedAccounts]),
|
|
155
|
-
keyCount: Buffer.from(keyCount),
|
|
156
|
-
keys: this.accountKeys.map((key) => key.toBuffer()),
|
|
157
|
-
recentBlockhash: bs58.decode(this.recentBlockhash),
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
let signData = Buffer.alloc(2048)
|
|
161
|
-
const length = signDataLayout.encode(transaction, signData)
|
|
162
|
-
instructionBuffer.copy(signData, length)
|
|
163
|
-
return signData.slice(0, length + instructionBuffer.length)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Decode a compiled message into a Message object.
|
|
168
|
-
*/
|
|
169
|
-
static from(buffer: Buffer | Uint8Array | Array<number>): Message {
|
|
170
|
-
// Slice up wire data
|
|
171
|
-
let byteArray = [...buffer]
|
|
172
|
-
|
|
173
|
-
const numRequiredSignatures = byteArray.shift()
|
|
174
|
-
const numReadonlySignedAccounts = byteArray.shift()
|
|
175
|
-
const numReadonlyUnsignedAccounts = byteArray.shift()
|
|
176
|
-
|
|
177
|
-
const accountCount = shortvec.decodeLength(byteArray)
|
|
178
|
-
let accountKeys = []
|
|
179
|
-
for (let i = 0; i < accountCount; i++) {
|
|
180
|
-
const account = byteArray.slice(0, PUBKEY_LENGTH)
|
|
181
|
-
byteArray = byteArray.slice(PUBKEY_LENGTH)
|
|
182
|
-
accountKeys.push(bs58.encode(Buffer.from(account)))
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH)
|
|
186
|
-
byteArray = byteArray.slice(PUBKEY_LENGTH)
|
|
187
|
-
|
|
188
|
-
const instructionCount = shortvec.decodeLength(byteArray)
|
|
189
|
-
let instructions = []
|
|
190
|
-
for (let i = 0; i < instructionCount; i++) {
|
|
191
|
-
let instruction = {}
|
|
192
|
-
instruction.programIdIndex = byteArray.shift()
|
|
193
|
-
const accountCount = shortvec.decodeLength(byteArray)
|
|
194
|
-
instruction.accounts = byteArray.slice(0, accountCount)
|
|
195
|
-
byteArray = byteArray.slice(accountCount)
|
|
196
|
-
const dataLength = shortvec.decodeLength(byteArray)
|
|
197
|
-
const data = byteArray.slice(0, dataLength)
|
|
198
|
-
instruction.data = bs58.encode(Buffer.from(data))
|
|
199
|
-
byteArray = byteArray.slice(dataLength)
|
|
200
|
-
instructions.push(instruction)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const messageArgs = {
|
|
204
|
-
header: {
|
|
205
|
-
numRequiredSignatures,
|
|
206
|
-
numReadonlySignedAccounts,
|
|
207
|
-
numReadonlyUnsignedAccounts,
|
|
208
|
-
},
|
|
209
|
-
recentBlockhash: bs58.encode(Buffer.from(recentBlockhash)),
|
|
210
|
-
accountKeys,
|
|
211
|
-
instructions,
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return new Message(messageArgs)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import * as BufferLayout from '@exodus/buffer-layout'
|
|
3
|
-
|
|
4
|
-
import { PublicKey } from './publickey'
|
|
5
|
-
import type { Blockhash } from './utils/blockhash'
|
|
6
|
-
import * as Layout from './utils/layout'
|
|
7
|
-
import type { FeeCalculator } from './utils/fee-calculator'
|
|
8
|
-
import { FeeCalculatorLayout } from './utils/fee-calculator'
|
|
9
|
-
import { toBuffer } from './utils/to-buffer'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* See https://github.com/solana-labs/solana/blob/0ea2843ec9cdc517572b8e62c959f41b55cf4453/sdk/src/nonce_state.rs#L29-L32
|
|
13
|
-
*
|
|
14
|
-
* @private
|
|
15
|
-
*/
|
|
16
|
-
const NonceAccountLayout = BufferLayout.struct([
|
|
17
|
-
BufferLayout.u32('version'),
|
|
18
|
-
BufferLayout.u32('state'),
|
|
19
|
-
Layout.publicKey('authorizedPubkey'),
|
|
20
|
-
Layout.publicKey('nonce'),
|
|
21
|
-
BufferLayout.struct([FeeCalculatorLayout], 'feeCalculator'),
|
|
22
|
-
])
|
|
23
|
-
|
|
24
|
-
export const NONCE_ACCOUNT_LENGTH = NonceAccountLayout.span
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* NonceAccount class
|
|
28
|
-
*/
|
|
29
|
-
export class NonceAccount {
|
|
30
|
-
authorizedPubkey: PublicKey
|
|
31
|
-
nonce: Blockhash
|
|
32
|
-
feeCalculator: FeeCalculator
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Deserialize NonceAccount from the account data.
|
|
36
|
-
*
|
|
37
|
-
* @param buffer account data
|
|
38
|
-
* @return NonceAccount
|
|
39
|
-
*/
|
|
40
|
-
static fromAccountData(buffer: Buffer | Uint8Array | Array<number>): NonceAccount {
|
|
41
|
-
const nonceAccount = NonceAccountLayout.decode(toBuffer(buffer), 0)
|
|
42
|
-
nonceAccount.authorizedPubkey = new PublicKey(nonceAccount.authorizedPubkey)
|
|
43
|
-
nonceAccount.nonce = new PublicKey(nonceAccount.nonce).toString()
|
|
44
|
-
return nonceAccount
|
|
45
|
-
}
|
|
46
|
-
}
|
package/src/vendor/publickey.js
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import BN from 'bn.js'
|
|
3
|
-
import bs58 from 'bs58'
|
|
4
|
-
import nacl from 'tweetnacl'
|
|
5
|
-
import createHash from 'create-hash'
|
|
6
|
-
|
|
7
|
-
// $FlowFixMe
|
|
8
|
-
let naclLowLevel = nacl.lowlevel
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Maximum length of derived pubkey seed
|
|
12
|
-
*/
|
|
13
|
-
export const MAX_SEED_LENGTH = 32
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* A public key
|
|
17
|
-
*/
|
|
18
|
-
export class PublicKey {
|
|
19
|
-
_bn: BN
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Create a new PublicKey object
|
|
23
|
-
*/
|
|
24
|
-
constructor(value: number | string | Buffer | Uint8Array | Array<number>) {
|
|
25
|
-
if (typeof value === 'string') {
|
|
26
|
-
// assume base 58 encoding by default
|
|
27
|
-
const decoded = bs58.decode(value)
|
|
28
|
-
if (decoded.length !== 32) {
|
|
29
|
-
throw new Error(`Invalid public key input`)
|
|
30
|
-
}
|
|
31
|
-
this._bn = new BN(decoded)
|
|
32
|
-
} else {
|
|
33
|
-
this._bn = new BN(value)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (this._bn.byteLength() > 32) {
|
|
37
|
-
throw new Error(`Invalid public key input`)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Checks if two publicKeys are equal
|
|
43
|
-
*/
|
|
44
|
-
equals(publicKey: PublicKey): boolean {
|
|
45
|
-
return this._bn.eq(publicKey._bn)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Return the base-58 representation of the public key
|
|
50
|
-
*/
|
|
51
|
-
toBase58(): string {
|
|
52
|
-
return bs58.encode(this.toBuffer())
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Return the Buffer representation of the public key
|
|
57
|
-
*/
|
|
58
|
-
toBuffer(): Buffer {
|
|
59
|
-
const b = this._bn.toArrayLike(Buffer)
|
|
60
|
-
if (b.length === 32) {
|
|
61
|
-
return b
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const zeroPad = Buffer.alloc(32)
|
|
65
|
-
b.copy(zeroPad, 32 - b.length)
|
|
66
|
-
return zeroPad
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Returns a string representation of the public key
|
|
71
|
-
*/
|
|
72
|
-
toString(): string {
|
|
73
|
-
return this.toBase58()
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Find a valid program address
|
|
78
|
-
*
|
|
79
|
-
* Valid program addresses must fall off the ed25519 curve. This function
|
|
80
|
-
* iterates a nonce until it finds one that when combined with the seeds
|
|
81
|
-
* results in a valid program address.
|
|
82
|
-
* HACK: transformed in sync function
|
|
83
|
-
*/
|
|
84
|
-
static findProgramAddress(seeds: Array<Buffer | Uint8Array>, programId: PublicKey) {
|
|
85
|
-
let nonce = 255
|
|
86
|
-
let address
|
|
87
|
-
while (nonce !== 0) {
|
|
88
|
-
try {
|
|
89
|
-
const seedsWithNonce = seeds.concat(Buffer.from([nonce]))
|
|
90
|
-
address = this.createProgramAddress(seedsWithNonce, programId)
|
|
91
|
-
} catch (err) {
|
|
92
|
-
nonce--
|
|
93
|
-
continue
|
|
94
|
-
}
|
|
95
|
-
return [address, nonce]
|
|
96
|
-
}
|
|
97
|
-
throw new Error('Unable to find a viable program address nonce')
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Derive a public key from another key, a seed, and a program ID.
|
|
102
|
-
* HACK: transformed in sync function
|
|
103
|
-
*/
|
|
104
|
-
static createWithSeed(
|
|
105
|
-
fromPublicKey: PublicKey,
|
|
106
|
-
seed: string,
|
|
107
|
-
programId: PublicKey
|
|
108
|
-
): Promise<PublicKey> {
|
|
109
|
-
const buffer = Buffer.concat([
|
|
110
|
-
fromPublicKey.toBuffer(),
|
|
111
|
-
Buffer.from(seed),
|
|
112
|
-
programId.toBuffer(),
|
|
113
|
-
])
|
|
114
|
-
const hash = createHash('sha256')
|
|
115
|
-
.update(buffer)
|
|
116
|
-
.digest('hex')
|
|
117
|
-
return new PublicKey(Buffer.from(hash, 'hex'))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Derive a program address from seeds and a program ID.
|
|
122
|
-
*/
|
|
123
|
-
static createProgramAddress(seeds: Array<Buffer | Uint8Array>, programId: PublicKey) {
|
|
124
|
-
let buffer = Buffer.alloc(0)
|
|
125
|
-
seeds.forEach(function(seed) {
|
|
126
|
-
if (seed.length > MAX_SEED_LENGTH) {
|
|
127
|
-
throw new Error('Max seed length exceeded')
|
|
128
|
-
}
|
|
129
|
-
buffer = Buffer.concat([buffer, Buffer.from(seed)])
|
|
130
|
-
})
|
|
131
|
-
buffer = Buffer.concat([buffer, programId.toBuffer(), Buffer.from('ProgramDerivedAddress')])
|
|
132
|
-
let hash = createHash('sha256')
|
|
133
|
-
.update(buffer)
|
|
134
|
-
.digest('hex')
|
|
135
|
-
let publicKeyBytes = new BN(hash, 16).toArray(null, 32)
|
|
136
|
-
if (isOnCurve(publicKeyBytes)) {
|
|
137
|
-
throw new Error('Invalid seeds, address must fall off the curve')
|
|
138
|
-
}
|
|
139
|
-
return new PublicKey(publicKeyBytes)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Check that a pubkey is on the curve.
|
|
144
|
-
// This function and its dependents were sourced from:
|
|
145
|
-
// https://github.com/dchest/tweetnacl-js/blob/f1ec050ceae0861f34280e62498b1d3ed9c350c6/nacl.js#L792
|
|
146
|
-
function isOnCurve(p) {
|
|
147
|
-
let r = [naclLowLevel.gf(), naclLowLevel.gf(), naclLowLevel.gf(), naclLowLevel.gf()]
|
|
148
|
-
|
|
149
|
-
let t = naclLowLevel.gf()
|
|
150
|
-
let chk = naclLowLevel.gf()
|
|
151
|
-
let num = naclLowLevel.gf()
|
|
152
|
-
let den = naclLowLevel.gf()
|
|
153
|
-
let den2 = naclLowLevel.gf()
|
|
154
|
-
let den4 = naclLowLevel.gf()
|
|
155
|
-
let den6 = naclLowLevel.gf()
|
|
156
|
-
|
|
157
|
-
naclLowLevel.set25519(r[2], gf1)
|
|
158
|
-
naclLowLevel.unpack25519(r[1], p)
|
|
159
|
-
naclLowLevel.S(num, r[1])
|
|
160
|
-
naclLowLevel.M(den, num, naclLowLevel.D)
|
|
161
|
-
naclLowLevel.Z(num, num, r[2])
|
|
162
|
-
naclLowLevel.A(den, r[2], den)
|
|
163
|
-
|
|
164
|
-
naclLowLevel.S(den2, den)
|
|
165
|
-
naclLowLevel.S(den4, den2)
|
|
166
|
-
naclLowLevel.M(den6, den4, den2)
|
|
167
|
-
naclLowLevel.M(t, den6, num)
|
|
168
|
-
naclLowLevel.M(t, t, den)
|
|
169
|
-
|
|
170
|
-
naclLowLevel.pow2523(t, t)
|
|
171
|
-
naclLowLevel.M(t, t, num)
|
|
172
|
-
naclLowLevel.M(t, t, den)
|
|
173
|
-
naclLowLevel.M(t, t, den)
|
|
174
|
-
naclLowLevel.M(r[0], t, den)
|
|
175
|
-
|
|
176
|
-
naclLowLevel.S(chk, r[0])
|
|
177
|
-
naclLowLevel.M(chk, chk, den)
|
|
178
|
-
if (neq25519(chk, num)) naclLowLevel.M(r[0], r[0], I)
|
|
179
|
-
|
|
180
|
-
naclLowLevel.S(chk, r[0])
|
|
181
|
-
naclLowLevel.M(chk, chk, den)
|
|
182
|
-
if (neq25519(chk, num)) return 0
|
|
183
|
-
return 1
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
let gf1 = naclLowLevel.gf([1])
|
|
187
|
-
let I = naclLowLevel.gf([
|
|
188
|
-
0xa0b0,
|
|
189
|
-
0x4a0e,
|
|
190
|
-
0x1b27,
|
|
191
|
-
0xc4ee,
|
|
192
|
-
0xe478,
|
|
193
|
-
0xad2f,
|
|
194
|
-
0x1806,
|
|
195
|
-
0x2f43,
|
|
196
|
-
0xd7a7,
|
|
197
|
-
0x3dfb,
|
|
198
|
-
0x0099,
|
|
199
|
-
0x2b4d,
|
|
200
|
-
0xdf0b,
|
|
201
|
-
0x4fc1,
|
|
202
|
-
0x2480,
|
|
203
|
-
0x2b83,
|
|
204
|
-
])
|
|
205
|
-
|
|
206
|
-
function neq25519(a, b) {
|
|
207
|
-
var c = new Uint8Array(32)
|
|
208
|
-
var d = new Uint8Array(32)
|
|
209
|
-
naclLowLevel.pack25519(c, a)
|
|
210
|
-
naclLowLevel.pack25519(d, b)
|
|
211
|
-
return naclLowLevel.crypto_verify_32(c, 0, d, 0)
|
|
212
|
-
}
|