-
Notifications
You must be signed in to change notification settings - Fork 247
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1372 from near/feat/client
feat: client
- Loading branch information
Showing
84 changed files
with
2,574 additions
and
740 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
env: | ||
es6: true | ||
node: true | ||
extends: | ||
- 'eslint:recommended' | ||
- 'plugin:@typescript-eslint/eslint-recommended' | ||
- 'plugin:@typescript-eslint/recommended' | ||
parser: '@typescript-eslint/parser' | ||
rules: | ||
no-inner-declarations: off | ||
indent: | ||
- error | ||
- 2 | ||
- SwitchCase: 1 | ||
'@typescript-eslint/no-explicit-any': off | ||
|
||
parserOptions: | ||
ecmaVersion: 2018 | ||
sourceType: module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
# @near-js/client | ||
|
||
This package provides a simple interface for interacting with the Near blockchain. As a modern, tree-shakeable package, | ||
it is intended to replace usage of `near-api-js`. | ||
|
||
### Installation | ||
```shell | ||
# npm | ||
npm i -s @near-js/client | ||
|
||
# pnpm | ||
pnpm add @near-js/client | ||
``` | ||
|
||
### Usage | ||
|
||
|
||
### Dependency Initialization | ||
This package uses a common interface for specifying dependencies for RPC providers and cryptographic signing, allowing | ||
a more flexible approach to composing functionality. | ||
|
||
#### RPC provider | ||
RPC providers are required for any blockchain interaction, e.g. block queries, transaction publishing. | ||
|
||
This interface makes use of the `FallbackRpcProvider`, making it configurable with multiple RPC endpoint URLs | ||
which can be cycled through when the current URL returns an error. | ||
|
||
Specifying by URL endpoints: | ||
```ts | ||
import { getProviderByEndpoints } from '@near-js/client'; | ||
|
||
const rpcProvider = getProviderByEndpoints('https://rpc.tld', 'https://fallback-rpc.tld'); | ||
``` | ||
|
||
Specifying by network (uses default RPC endpoints specified in code): | ||
```ts | ||
import { getProviderByNetwork } from '@near-js/client'; | ||
|
||
const rpcProvider = getProviderByNetwork('testnet'); | ||
``` | ||
|
||
Shortcut methods: | ||
```ts | ||
import { getTestnetRpcProvider } from '@near-js/client'; | ||
|
||
// equivalent to getProviderByNetwork('testnet'); | ||
const rpcProvider = getTestnetRpcProvider(); | ||
``` | ||
|
||
#### Message Signer | ||
Implementers of the `MessageSigner` interface can be initialized from the existing `KeyStore` classes or using private keys. | ||
|
||
Using an existing keystore: | ||
```ts | ||
import { getSignerFromKeystore } from '@near-js/client'; | ||
import { BrowserLocalStorageKeyStore } from '@near-js/keystores-browser'; | ||
|
||
const keystore = new BrowserLocalStorageKeyStore(); | ||
const signer = getSignerFromKeystore('account.near', 'mainnet', keystore); | ||
``` | ||
|
||
|
||
Using a private key string: | ||
```ts | ||
import { getSignerFromKeystore } from '@near-js/client'; | ||
import { BrowserLocalStorageKeyStore } from '@near-js/keystores-browser'; | ||
|
||
const signer = getSignerFromPrivateKey('ed25519:...'); | ||
``` | ||
|
||
An access key-based signer is also available. Initialized using a `MessageSigner` implementer, this signer caches the | ||
access key record and maintains a local, auto-incremented value for its nonce: | ||
```ts | ||
import { getAccessKeySigner, getMainnetRpcProvider, getSignerFromPrivateKey } from '@near-js/client'; | ||
import { BrowserLocalStorageKeyStore } from '@near-js/keystores-browser'; | ||
|
||
const keystore = new BrowserLocalStorageKeyStore(); | ||
const signer = getSignerFromKeystore('account.near', 'mainnet', keystore); | ||
const accessKeySigner = getAccessKeySigner({ | ||
accout: 'account.near', | ||
deps: { | ||
signer, | ||
rpcProvider: getMainnetRpcProvider(), | ||
}, | ||
}); | ||
``` | ||
|
||
### View Methods | ||
Several functions are provided for working with builtin account methods and smart contract view methods. | ||
|
||
Executing a view method on a smart contract and return the entire response: | ||
```ts | ||
import { callViewMethod, getTestnetRpcProvider } from '@near-js/client'; | ||
|
||
const response = await callViewMethod({ | ||
account: 'guest-book.testnet', | ||
method: 'getMessages', | ||
deps: { rpcProvider: getTestnetRpcProvider() }, | ||
}); | ||
``` | ||
|
||
Shorthand function to call the method and return only the parsed value: | ||
```ts | ||
import { getTestnetRpcProvider, view } from '@near-js/client'; | ||
|
||
interface GuestBookMessage { | ||
premium: boolean; | ||
sender: string; | ||
text: string; | ||
} | ||
|
||
// parse the returned buffer and parse as JSON | ||
const data = await view<GuestBookMessage[]>({ | ||
account: 'guest-book.testnet', | ||
method: 'getMessages', | ||
deps: { rpcProvider: getTestnetRpcProvider() }, | ||
}); | ||
``` | ||
|
||
Client method for requesting access keys: | ||
```ts | ||
import { getAccessKeys, getTestnetRpcProvider } from '@near-js/client'; | ||
|
||
const { fullAccessKeys, functionCallAccessKeys } = await getAccessKeys({ | ||
account: 'account.testnet', | ||
deps: { rpcProvider: getTestnetRpcProvider() }, | ||
}); | ||
``` | ||
|
||
### Transactions | ||
New `*Composer` classes facilitate transaction building and signing: | ||
```ts | ||
import { | ||
getSignerFromKeystore, | ||
getTestnetRpcProvider, | ||
SignedTransactionComposer, | ||
} from '@near-js/client'; | ||
import { KeyPairEd25519 } from '@near-js/crypto'; | ||
import { BrowserLocalStorageKeyStore } from '@near-js/keystores-browser'; | ||
|
||
const keystore = new BrowserLocalStorageKeyStore(); | ||
const signer = getSignerFromKeystore('account.testnet', 'testnet', keystore); | ||
|
||
const oldPublicKey = await signer.getPublicKey(); | ||
const newKeyPair = KeyPairEd25519.fromRandom(); | ||
|
||
const composer = SignedTransactionComposer.init({ | ||
sender: 'account.testnet', | ||
receiver: 'receiver.testnet', | ||
deps: { | ||
signer, | ||
rpcProvider: getMainnetRpcProvider(), | ||
} | ||
}); | ||
|
||
// add new key and remove old key in single transaction | ||
await composer | ||
.addFullAccessKey(newKeyPair.publicKey) | ||
.deleteKey(oldPublicKey.toString()) | ||
.signAndSend(); | ||
|
||
keystore.setKey('testnet', 'account.testnet', newKeyPair); | ||
``` | ||
|
||
For convenience, there are also functions wrapping individual actions, e.g. `transfer`: | ||
```ts | ||
import { | ||
getSignerFromKeystore, | ||
getTestnetRpcProvider, | ||
transfer, | ||
} from '@near-js/client'; | ||
import { KeyPairEd25519 } from '@near-js/crypto'; | ||
import { BrowserLocalStorageKeyStore } from '@near-js/keystores-browser'; | ||
|
||
const keystore = new BrowserLocalStorageKeyStore(); | ||
const signer = getSignerFromKeystore('account.testnet', 'testnet', keystore); | ||
|
||
await transfer({ | ||
sender: 'account.testnet', | ||
receiver: 'receiver.testnet', | ||
amount: 1000n, // in yoctoNear | ||
deps: { | ||
rpcProvider: getTestnetRpcProvider(), | ||
signer, | ||
} | ||
}); | ||
``` | ||
|
||
# License | ||
|
||
This repository is distributed under the terms of both the MIT license and the Apache License (Version 2.0). | ||
See [LICENSE](https://github.com/near/near-api-js/blob/master/LICENSE) and [LICENSE-APACHE](https://github.com/near/near-api-js/blob/master/LICENSE-APACHE) for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export default { | ||
preset: 'ts-jest', | ||
collectCoverage: true, | ||
testEnvironment: 'node', | ||
testRegex: "(/tests/.*|(\\.|/)(test|spec))\\.[jt]sx?$", | ||
transform: { | ||
'^.+\\.[tj]s$': ['ts-jest', { | ||
tsconfig: { | ||
allowJs: true, | ||
}, | ||
}], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "@near-js/client", | ||
"version": "0.0.1", | ||
"description": "", | ||
"main": "lib/esm/index.js", | ||
"type": "module", | ||
"scripts": { | ||
"build": "pnpm compile:esm && pnpm compile:cjs", | ||
"compile:esm": "tsc -p tsconfig.json", | ||
"compile:cjs": "tsc -p tsconfig.cjs.json && cjsify ./lib/commonjs", | ||
"lint": "eslint -c .eslintrc.yml src/**/*.ts --no-eslintrc --no-error-on-unmatched-pattern", | ||
"lint:fix": "eslint -c .eslintrc.yml src/**/*.ts --no-eslintrc --no-error-on-unmatched-pattern --fix" | ||
}, | ||
"dependencies": { | ||
"@near-js/crypto": "workspace:*", | ||
"@near-js/keystores": "workspace:*", | ||
"@near-js/providers": "workspace:*", | ||
"@near-js/signers": "workspace:*", | ||
"@near-js/transactions": "workspace:*", | ||
"@near-js/types": "workspace:*", | ||
"@near-js/utils": "workspace:*", | ||
"@noble/hashes": "1.3.3", | ||
"isomorphic-fetch": "3.0.0" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"devDependencies": { | ||
"@types/node": "20.0.0", | ||
"build": "workspace:*", | ||
"tsconfig": "workspace:*", | ||
"typescript": "5.4.5" | ||
}, | ||
"files": [ | ||
"lib" | ||
], | ||
"exports": { | ||
"require": "./lib/commonjs/index.cjs", | ||
"import": "./lib/esm/index.js" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
export const DEFAULT_META_TRANSACTION_BLOCK_HEIGHT_TTL = 100n; | ||
export const MAX_GAS = 300000000000000n; | ||
|
||
export const PAGODA_RPC_ENDPOINTS_MAINNET = [ | ||
'https://rpc.near.org', | ||
'https://rpc.mainnet.pagoda.co', | ||
]; | ||
|
||
export const PAGODA_RPC_ARCHIVAL_ENDPOINTS_MAINNET = [ | ||
'https://archival-rpc.near.org', | ||
]; | ||
|
||
export const PAGODA_RPC_ENDPOINTS_TESTNET = [ | ||
'https://rpc.testnet.near.org', | ||
'https://rpc.testnet.pagoda.co', | ||
]; | ||
|
||
export const PAGODA_RPC_ARCHIVAL_ENDPOINTS_TESTNET = [ | ||
'https://archival-rpc.testnet.near.org', | ||
]; | ||
|
||
export const KITWALLET_FUNDED_TESTNET_ACCOUNT_ENDPOINT = 'https://testnet-api.kitwallet.app/account'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { CurveType, KeyPair, KeyPairString } from '@near-js/crypto'; | ||
|
||
/** | ||
* Generate a random key pair for the specified elliptic curve | ||
* @param curve elliptic curve (e.g. `ed25519`) | ||
*/ | ||
export function generateRandomKeyPair(curve: CurveType) { | ||
return KeyPair.fromRandom(curve); | ||
} | ||
|
||
/** | ||
* Parse a signing key pair from a private key string | ||
* @param privateKey private key string | ||
*/ | ||
export function parseKeyPair(privateKey: KeyPairString) { | ||
return KeyPair.fromString(privateKey); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import type { FinalExecutionOutcome } from '@near-js/types'; | ||
import fetch from 'isomorphic-fetch'; | ||
|
||
import { KITWALLET_FUNDED_TESTNET_ACCOUNT_ENDPOINT } from './constants'; | ||
import { NewAccountParams } from './interfaces'; | ||
|
||
interface CreateFundedTestnetAccountParams extends NewAccountParams { | ||
endpointUrl?: string; | ||
} | ||
|
||
/** | ||
* Create a new funded testnet account via faucet REST endpoint | ||
* (e.g. create `new.testnet` with a preset amount of Near) | ||
* @param endpointUrl REST endpoint for the funded testnet account creation (defaults to the current Near Contract Helper endpoint) | ||
* @param newAccount name of the created account | ||
* @param newPublicKey public key for the created account's initial full access key | ||
*/ | ||
export async function createFundedTestnetAccount({ | ||
newAccount, | ||
newPublicKey, | ||
endpointUrl = KITWALLET_FUNDED_TESTNET_ACCOUNT_ENDPOINT, | ||
}: CreateFundedTestnetAccountParams) { | ||
const res = await fetch(endpointUrl, { | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
newAccountId: newAccount, | ||
newAccountPublicKey: newPublicKey, | ||
}), | ||
headers: { 'Content-Type': 'application/json' }, | ||
}); | ||
|
||
const { ok, status } = res; | ||
if (!ok) { | ||
throw new Error(`Failed to create account on ${endpointUrl}: ${status}`); | ||
} | ||
|
||
return await res.json() as FinalExecutionOutcome; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export { formatNearAmount } from '@near-js/utils'; | ||
|
||
export * from './constants'; | ||
export * from './crypto'; | ||
export * from './funded_account'; | ||
export * from './interfaces'; | ||
export * from './providers'; | ||
export * from './signing'; | ||
export * from './transactions'; | ||
export * from './view'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { PublicKey } from '@near-js/crypto'; | ||
|
||
import type { RpcQueryProvider } from './providers'; | ||
import { FullAccessKey, FunctionCallAccessKey } from './view'; | ||
|
||
interface Dependent<T> { | ||
deps: T; | ||
} | ||
|
||
export interface MessageSigner { | ||
getPublicKey(): Promise<PublicKey>; | ||
signMessage(m: Uint8Array): Promise<Uint8Array>; | ||
} | ||
|
||
export interface AccessKeySigner extends MessageSigner { | ||
getAccessKey(ignoreCache?: boolean): Promise<FullAccessKey | FunctionCallAccessKey>; | ||
getNonce(ignoreCache?: boolean): Promise<bigint>; | ||
getSigningAccount(): string; | ||
} | ||
|
||
interface RpcProviderDependent { | ||
rpcProvider: RpcQueryProvider; | ||
} | ||
|
||
interface SignerDependent { | ||
signer: MessageSigner; | ||
} | ||
|
||
export interface RpcProviderDependency extends Dependent<RpcProviderDependent> {} | ||
|
||
export interface SignerDependency extends Dependent<SignerDependent> {} | ||
|
||
export interface SignAndSendTransactionDependency extends Dependent<RpcProviderDependent & SignerDependent> {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './dependencies'; | ||
export * from './providers'; | ||
export * from './transactions'; | ||
export * from './view'; |
Oops, something went wrong.