NEAR JavaScript API에 대한 FAQ
커뮤니티에서 자주 묻는 질문 모음입니다.
일반
near-api-js
를 정적 html 페이지에서 사용할 수 있나요?
CDN에서 스크립트를 로드할 수 있습니다.
<script src="https://cdn.jsdelivr.net/npm/near-api-js@0.45.1/dist/near-api-js.min.js"></script>
버전 목록은 npmjs.com에 있습니다.
구현 예시
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="messages"></ul>
<textarea id="text" placeholder="Add Message"></textarea>
<button id="add-text">Add Text</button>
<script src="https://cdn.jsdelivr.net/npm/near-api-js@0.45.1/dist/near-api-js.min.js"></script>
<script>
// connect to NEAR
const near = new nearApi.Near({
keyStore: new nearApi.keyStores.BrowserLocalStorageKeyStore(),
networkId: 'testnet',
nodeUrl: 'https://rpc.testnet.near.org',
walletUrl: 'https://testnet.mynearwallet.com/'
});
// connect to the NEAR Wallet
const wallet = new nearApi.WalletConnection(near, 'my-app');
// connect to a NEAR smart contract
const contract = new nearApi.Contract(wallet.account(), 'guest-book.testnet', {
viewMethods: ['getMessages'],
changeMethods: ['addMessage']
});
const button = document.getElementById('add-text');
if (!wallet.isSignedIn()) {
button.textContent = 'SignIn with NEAR'
}
// call the getMessages view method
contract.getMessages()
.then(messages => {
const ul = document.getElementById('messages');
messages.forEach(message => {
const li = document.createElement('li');
li.textContent = `${message.sender} - ${message.text}`;
ul.appendChild(li);
})
});
// Either sign in or call the addMessage change method on button click
document.getElementById('add-text').addEventListener('click', () => {
if (wallet.isSignedIn()) {
contract.addMessage({
args: { text: document.getElementById('text').value },
amount: nearApi.utils.format.parseNearAmount('1')
})
} else {
wallet.requestSignIn({
contractId: 'guest-book.testnet',
methodNames: ['getMessages', 'addMessage']
});
}
});
</script>
</body>
</html>
어떤 프론트엔드 프레임워크에서 JavaScript API를 사용할 수 있나요?
JavaScript API는 프레임워크에 구애받지 않습니다. React, Vue, Angular 등과 같은 모든 프론트엔드 프레임워크를 사용할 수 있습니다.
create-near-app
은 여러 템플릿으로 프로젝트를 빠르게 부트스트랩하는 데 사용될 수 있는 도구입니다.
npx create-near-app
React Native와 같은 모바일 JavaScript 프레임워크에서 JavaScript API를 사용할 수 있나요?
JavaScript API는 대부분의 JavaScript 런타임에서 사용할 수 있으며, 내부적으로는 NEAR의 RPC API에 대한 추 상화입니다. 그러나 지갑을 모든 곳에서 사용할 수는 없습니다. 예를 들어, React Native 앱에서는 앱의 웹 버전에서 지갑을 사용할 수 있지만, 기본 앱 배포에서는 작동하지 않습니다.
iOS 또는 Android 내 WebView
구성 요소에서 지갑을 사용할 수 있지만, 이는 KeyStore
에 대해 LocalStorage
를 사용하고, WebView
구성 요소 로딩를 관리할 때 스토리지를 유지하는 것은 사용자의 책임이라는 것을 기억하세요.
트랜잭션
트랜잭션 상태 확인 방법
요리책에서 트랜잭션에 대한 예를 참조하세요.
near-api-js에 의해 트랜잭션이 서명되고 전송되는 방법
트랜잭션 데이터가 네트워크에 전달되고 최종적으로 블록에 포함되기 전에 관련된 몇 가지 단계가 있습니다. 다음 단계는 사용자 계정에서 트랜잭션을 생성, 서명 및 최종적으로 수행할 때 수행됩니다.
- 사용자는
account.signAndSendTransaction
메서드를를 사용하여 트랜잭션 객체를 생성합니다. 이 메서드는 Action 배열을 수락하고 트랜잭션 결과에 대한 객체를 반환합니다. - 트랜잭션은 account.signTransaction 메서드를 사용하여 서명됩니다. 이 메서드는 Action 배열을 수락하고 서명된 트랜잭션 객체를 반환합니다.
- 서명된 트랜잭션 객체는
account.connection.provider.sendTransaction
메서드를 통해 네트워크로 전송됩니다. 이 메서드는 서명된 트랜잭션 객체를 수락하고 트랜잭션 해시를 반환합니다. 이 단계는 트랜잭션 객체에 대한 borsh 직렬화를 수행하고 base64로 인코딩된 직렬화된 트랜잭션 개체로 JSON RPC 메서드broadcast_tx_commit
를 호출합니다.
배치(Batch) 트랜잭션 전송 방법
account
에서 signAndSendTransaction({})
메서드를 사용하여 트랜잭션을 일괄 전송할 수 있습니다. 이 메서드는 일련의 트랜잭션 작업을 수행하며, 하나가 실패하면 전체 작업이 실패합니다. 다음은 간단한 예입니다.
const { connect, transactions, keyStores } = require("near-api-js");
const fs = require("fs");
const path = require("path");
const homedir = require("os").homedir();
const CREDENTIALS_DIR = ".near-credentials";
const CONTRACT_NAME = "spf.idea404.testnet";
const WASM_PATH = path.join(__dirname, "../build/uninitialized_nft.wasm");
const credentialsPath = path.join(homedir, CREDENTIALS_DIR);
const keyStore = new keyStores.UnencryptedFileSystemKeyStore(credentialsPath);
const config = {
keyStore,
networkId: "testnet",
nodeUrl: "https://rpc.testnet.near.org",
};
sendTransactions();
async function sendTransactions() {
const near = await connect({ ...config, keyStore });
const account = await near.account(CONTRACT_NAME);
const args = { some_field: 1, another_field: "hello" };
const balanceBefore = await account.getAccountBalance();
console.log("Balance before:", balanceBefore);
try {
const result = await account.signAndSendTransaction({
receiverId: CONTRACT_NAME,
actions: [
transactions.deployContract(fs.readFileSync(WASM_PATH)), // Contract does not get deployed
transactions.functionCall("new", Buffer.from(JSON.stringify(args)), 10000000000000, "0"), // this call fails
transactions.transfer("1" + "0".repeat(24)), // 1 NEAR is not transferred either
],
});
console.log(result);
} catch (e) {
console.log("Error:", e);
}
const balanceAfter = await account.getAccountBalance();
console.log("Balance after:", balanceAfter);
}
Balance before: {
total: '49987878054959838200000000',
stateStaked: '4555390000000000000000000',
staked: '0',
available: '45432488054959838200000000'
}
Receipts: 2PPueY6gnA4YmmQUzc8DytNBp4PUpgTDhmEjRSHHVHBd, 3isLCW9SBH1MrPjeEPAmG9saHLj9Z2g7HxzfBdHmaSaG
Failure [spf.idea404.testnet]: Error: {"index":1,"kind":{"ExecutionError":"Smart contract panicked: panicked at 'Failed to deserialize input from JSON.: Error(\"missing field `owner_id`\", line: 1, column: 40)', nft/src/lib.rs:47:1"}}
Error: ServerTransactionError: {"index":1,"kind":{"ExecutionError":"Smart contract panicked: panicked at 'Failed to deserialize input from JSON.: Error(\"missing field `owner_id`\", line: 1, column: 40)', nft/src/lib.rs:47:1"}}
at parseResultError (/Users/dennis/Code/naj-test/node_modules/near-api-js/lib/utils/rpc_errors.js:31:29)
at Account.<anonymous> (/Users/dennis/Code/naj-test/node_modules/near-api-js/lib/account.js:156:61)
at Generator.next (<anonymous>)
at fulfilled (/Users/dennis/Code/naj-test/node_modules/near-api-js/lib/account.js:5:58)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
type: 'FunctionCallError',
context: undefined,
index: 1,
kind: {
ExecutionError: 'Smart contract panicked: panicked at \'Failed to deserialize input from JSON.: Error("missing field `owner_id`", line: 1, column: 40)\', nft/src/lib.rs:47:1'
},
transaction_outcome: {
block_hash: '5SUhYcXjXR1svCxL5BhCuw88XNdEjKXqWgA9X4XZW1dW',
id: 'SKQqAgnSN27fyHpncaX3fCUxWknBrMtxxytWLRDQfT3',
outcome: {
executor_id: 'spf.idea404.testnet',
gas_burnt: 4839199843770,
logs: [],
metadata: [Object],
receipt_ids: [Array],
status: [Object],
tokens_burnt: '483919984377000000000'
},
proof: [ [Object], [Object], [Object], [Object], [Object] ]
}
}
Balance after: {
total: '49985119959346682700000000',
stateStaked: '4555390000000000000000000',
staked: '0',
available: '45429729959346682700000000'
}
요리책에서 배치 트랜잭션의 예를 찾을 수도 있습니다.