near-encoding 1.0.0 → 1.1.7619
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 +20 -12
- package/index.js +57 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# near-encoding
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utility functions for encoding, decoding, and interacting with the NEAR blockchain.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
npm install near-encoding
|
|
8
8
|
|
|
9
|
-
## API
|
|
9
|
+
## API
|
|
10
10
|
|
|
11
11
|
### `encodeBase64(input: string): string`
|
|
12
12
|
|
|
@@ -16,6 +16,8 @@ import { encodeBase64 } from 'near-encoding';
|
|
|
16
16
|
|
|
17
17
|
const encoded = encodeBase64('hello world');
|
|
18
18
|
|
|
19
|
+
---
|
|
20
|
+
|
|
19
21
|
### `decodeBase64(input: string): string`
|
|
20
22
|
|
|
21
23
|
Decodes a Base64 string back to UTF-8.
|
|
@@ -24,34 +26,40 @@ import { decodeBase64 } from 'near-encoding';
|
|
|
24
26
|
|
|
25
27
|
const decoded = decodeBase64('aGVsbG8gd29ybGQ=');
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
### `encodeArgs(args: Record<string, unknown>): Buffer`
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
Serializes a plain object into a UTF-8 encoded `Buffer` for use in NEAR contract calls.
|
|
30
34
|
|
|
31
35
|
import { encodeArgs } from 'near-encoding';
|
|
32
36
|
|
|
33
|
-
const
|
|
37
|
+
const buffer = encodeArgs({ token_id: '123', receiver_id: 'alice.near' });
|
|
38
|
+
|
|
39
|
+
---
|
|
34
40
|
|
|
35
41
|
### `functionCall(options: FunctionCallOptions): Promise<nearApiJs.providers.FinalExecutionOutcome>`
|
|
36
42
|
|
|
37
|
-
Executes a
|
|
43
|
+
Executes a change-method call on a NEAR contract.
|
|
38
44
|
|
|
39
45
|
import { functionCall } from 'near-encoding';
|
|
40
46
|
|
|
41
47
|
const outcome = await functionCall({
|
|
42
|
-
|
|
43
|
-
contractId: '
|
|
48
|
+
accountId: 'alice.near',
|
|
49
|
+
contractId: 'token.near',
|
|
44
50
|
methodName: 'transfer',
|
|
45
|
-
args: { receiver_id: 'bob.near', amount: '
|
|
51
|
+
args: { receiver_id: 'bob.near', amount: '100' },
|
|
46
52
|
});
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### `generateKeyPair(accountId: string): GeneratedKeyPair`
|
|
49
57
|
|
|
50
|
-
Generates a new
|
|
58
|
+
Generates a new key pair associated with the given account ID.
|
|
51
59
|
|
|
52
60
|
import { generateKeyPair } from 'near-encoding';
|
|
53
61
|
|
|
54
|
-
const keyPair = generateKeyPair();
|
|
62
|
+
const keyPair = generateKeyPair('alice.near');
|
|
55
63
|
|
|
56
64
|
## License
|
|
57
65
|
|
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as nearApiJs from 'near-api-js';
|
|
2
|
-
import { KeyPair
|
|
2
|
+
import { KeyPair } from 'near-api-js';
|
|
3
|
+
import { KeyPairEd25519 } from 'near-api-js/lib/utils/key_pair';
|
|
3
4
|
|
|
4
5
|
const RPC_URL = 'https://rpc.mainnet.near.org';
|
|
5
6
|
|
|
@@ -8,149 +9,137 @@ export function encodeBase64(input: string): string {
|
|
|
8
9
|
return Buffer.from(input, 'utf8').toString('base64');
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
/** Decode a base64 string back to
|
|
12
|
+
/** Decode a base64 string back to UTF-8 */
|
|
12
13
|
export function decodeBase64(input: string): string {
|
|
13
14
|
return Buffer.from(input, 'base64').toString('utf8');
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
/** Encode
|
|
17
|
-
export function encodeArgs(args: Record<string, unknown>):
|
|
18
|
-
return
|
|
17
|
+
/** Encode an object to a borsh-compatible JSON Buffer for NEAR contract args */
|
|
18
|
+
export function encodeArgs(args: Record<string, unknown>): Buffer {
|
|
19
|
+
return Buffer.from(JSON.stringify(args), 'utf8');
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
/** Decode a base64-encoded NEAR
|
|
22
|
-
export function
|
|
23
|
-
|
|
22
|
+
/** Decode a base64-encoded NEAR contract result to a typed object */
|
|
23
|
+
export function decodeResult<T = unknown>(base64Result: string): T {
|
|
24
|
+
const json = Buffer.from(base64Result, 'base64').toString('utf8');
|
|
25
|
+
return JSON.parse(json) as T;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export interface ViewCallOptions {
|
|
27
|
-
/** NEAR account id of the contract */
|
|
28
29
|
contractId: string;
|
|
29
|
-
/** Method name to call */
|
|
30
30
|
methodName: string;
|
|
31
|
-
/** Arguments passed to the view method */
|
|
32
31
|
args?: Record<string, unknown>;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
export interface ViewCallResult<T = unknown> {
|
|
36
35
|
result: T;
|
|
37
|
-
|
|
36
|
+
raw: string;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
/**
|
|
41
|
-
* Call a NEAR view function via RPC and return both the decoded result and its
|
|
42
|
-
* raw base64-encoded form.
|
|
43
|
-
*/
|
|
39
|
+
/** Call a NEAR view function and return decoded result via RPC */
|
|
44
40
|
export async function viewCall<T = unknown>(
|
|
45
41
|
options: ViewCallOptions
|
|
46
42
|
): Promise<ViewCallResult<T>> {
|
|
47
43
|
const { contractId, methodName, args = {} } = options;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const body = {
|
|
51
|
-
jsonrpc: '2.0',
|
|
52
|
-
id: 'near-encoding',
|
|
53
|
-
method: 'query',
|
|
54
|
-
params: {
|
|
55
|
-
request_type: 'call_function',
|
|
56
|
-
finality: 'final',
|
|
57
|
-
account_id: contractId,
|
|
58
|
-
method_name: methodName,
|
|
59
|
-
args_base64: encodedArgs,
|
|
60
|
-
},
|
|
61
|
-
};
|
|
44
|
+
const argsBase64 = encodeBase64(JSON.stringify(args));
|
|
62
45
|
|
|
63
46
|
const response = await fetch(RPC_URL, {
|
|
64
47
|
method: 'POST',
|
|
65
48
|
headers: { 'Content-Type': 'application/json' },
|
|
66
|
-
body: JSON.stringify(
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
jsonrpc: '2.0',
|
|
51
|
+
id: 'near-encoding',
|
|
52
|
+
method: 'query',
|
|
53
|
+
params: {
|
|
54
|
+
request_type: 'call_function',
|
|
55
|
+
finality: 'final',
|
|
56
|
+
account_id: contractId,
|
|
57
|
+
method_name: methodName,
|
|
58
|
+
args_base64: argsBase64,
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
67
61
|
});
|
|
68
62
|
|
|
69
63
|
if (!response.ok) {
|
|
70
64
|
throw new Error(`RPC HTTP error: ${response.status}`);
|
|
71
65
|
}
|
|
72
66
|
|
|
73
|
-
const json =
|
|
74
|
-
result?: { result: number[] };
|
|
75
|
-
error?: { message: string };
|
|
76
|
-
};
|
|
67
|
+
const json = await response.json();
|
|
77
68
|
|
|
78
69
|
if (json.error) {
|
|
79
|
-
throw new Error(`RPC error: ${json.error
|
|
70
|
+
throw new Error(`RPC error: ${JSON.stringify(json.error)}`);
|
|
80
71
|
}
|
|
81
72
|
|
|
82
|
-
const raw =
|
|
83
|
-
|
|
84
|
-
|
|
73
|
+
const raw: string = Buffer.from(
|
|
74
|
+
json.result.result as number[],
|
|
75
|
+
'binary' as BufferEncoding
|
|
76
|
+
)
|
|
77
|
+
.toString('base64');
|
|
85
78
|
|
|
86
|
-
|
|
79
|
+
const decoded = decodeResult<T>(raw);
|
|
80
|
+
return { result: decoded, raw };
|
|
87
81
|
}
|
|
88
82
|
|
|
89
83
|
export interface FunctionCallOptions {
|
|
90
|
-
|
|
91
|
-
signerId: string;
|
|
92
|
-
/** NEAR account id of the contract */
|
|
84
|
+
accountId: string;
|
|
93
85
|
contractId: string;
|
|
94
|
-
/** Method name to call */
|
|
95
86
|
methodName: string;
|
|
96
|
-
/** Arguments to pass to the contract method */
|
|
97
87
|
args?: Record<string, unknown>;
|
|
98
|
-
/** Amount of NEAR to attach in yoctoNEAR */
|
|
99
|
-
attachedDeposit?: string;
|
|
100
|
-
/** Gas to attach (default: 30 Tgas) */
|
|
101
88
|
gas?: string;
|
|
102
|
-
|
|
103
|
-
keyPair
|
|
89
|
+
attachedDeposit?: string;
|
|
90
|
+
keyPair?: nearApiJs.KeyPair;
|
|
91
|
+
networkId?: string;
|
|
104
92
|
}
|
|
105
93
|
|
|
106
|
-
/**
|
|
107
|
-
* Execute a NEAR smart-contract function call, encoding args automatically.
|
|
108
|
-
* Returns the transaction outcome from the RPC.
|
|
109
|
-
*/
|
|
94
|
+
/** Execute a NEAR state-changing function call using near-api-js Account */
|
|
110
95
|
export async function functionCall(
|
|
111
96
|
options: FunctionCallOptions
|
|
112
97
|
): Promise<nearApiJs.providers.FinalExecutionOutcome> {
|
|
113
98
|
const {
|
|
114
|
-
|
|
99
|
+
accountId,
|
|
115
100
|
contractId,
|
|
116
101
|
methodName,
|
|
117
102
|
args = {},
|
|
118
|
-
attachedDeposit = '0',
|
|
119
103
|
gas = '30000000000000',
|
|
104
|
+
attachedDeposit = '0',
|
|
120
105
|
keyPair,
|
|
106
|
+
networkId = 'mainnet',
|
|
121
107
|
} = options;
|
|
122
108
|
|
|
123
109
|
const keyStore = new nearApiJs.keyStores.InMemoryKeyStore();
|
|
124
|
-
|
|
110
|
+
|
|
111
|
+
if (keyPair) {
|
|
112
|
+
await keyStore.setKey(networkId, accountId, keyPair);
|
|
113
|
+
}
|
|
125
114
|
|
|
126
115
|
const near = await nearApiJs.connect({
|
|
127
|
-
networkId
|
|
128
|
-
nodeUrl: RPC_URL,
|
|
116
|
+
networkId,
|
|
129
117
|
keyStore,
|
|
118
|
+
nodeUrl: RPC_URL,
|
|
130
119
|
});
|
|
131
120
|
|
|
132
|
-
const account = await near.account(
|
|
121
|
+
const account = await near.account(accountId);
|
|
133
122
|
|
|
134
|
-
|
|
123
|
+
return account.functionCall({
|
|
135
124
|
contractId,
|
|
136
125
|
methodName,
|
|
137
|
-
args,
|
|
138
|
-
attachedDeposit: BigInt(attachedDeposit),
|
|
126
|
+
args: encodeArgs(args),
|
|
139
127
|
gas: BigInt(gas),
|
|
128
|
+
attachedDeposit: BigInt(attachedDeposit),
|
|
140
129
|
});
|
|
141
|
-
|
|
142
|
-
return outcome;
|
|
143
130
|
}
|
|
144
131
|
|
|
145
132
|
export interface GeneratedKeyPair {
|
|
133
|
+
accountId: string;
|
|
146
134
|
publicKey: string;
|
|
147
|
-
keyPair: KeyPair;
|
|
135
|
+
keyPair: nearApiJs.KeyPair;
|
|
148
136
|
}
|
|
149
137
|
|
|
150
|
-
/** Generate a new
|
|
151
|
-
export function generateKeyPair(): GeneratedKeyPair {
|
|
138
|
+
/** Generate a new ed25519 KeyPair for a given accountId (no private key param accepted) */
|
|
139
|
+
export function generateKeyPair(accountId: string): GeneratedKeyPair {
|
|
152
140
|
const keyPair = KeyPairEd25519.fromRandom();
|
|
153
141
|
return {
|
|
142
|
+
accountId,
|
|
154
143
|
publicKey: keyPair.getPublicKey().toString(),
|
|
155
144
|
keyPair,
|
|
156
145
|
};
|