Японская версия 👉 здесь
Английская версия 👉 здесь
Что такое Node.js и NPM?
Node.js — это целая платформа для создания серверных приложений на языке программирования JavaScript. Node.js основан на модульной системе, позволяющей добавлять в приложение отдельные пакеты.
Node.js использует диспетчер пакетов Node (npm) для управления зависимостями. Это позволяет загружать и устанавливать необходимые для проекта модули из сторонних источников.
TL;DR
1.Какова мотивация создания NEMTUS @nemtus/symbol-sdk-typescript?
- Мотивация состояла в том, чтобы использовать эквивалентную функциональность symbol-sdk v3, реализованную на JS в среде TypeScript, без стресса и без каких-либо специальных настроек.
2. Как @nemtus/symbol-sdk-typescript был создан из symbol-sdk v3, реализованного для JavaScript, в TypeScript самым простым способом?
- Он был создан путем сборки оригинального symbol-sdk v3 по следующей ссылке.
i.https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html
b) Дополнительные сведения см. по следующим ссылкам на репозиторий SDK и пакет npm (Node Package Manager).
i.https://github.com/nemtus/symbol/tree/dev/sdk/javascript
ii.https://www.npmjs.com/package/@nemtus/symbol-sdk-typescript
3. Как отправлять транзакции в блокчейне Symbol с помощью @nemtus/symbol-sdk-typescript
a.Пожалуйста, обратитесь к исходному коду по ссылке ниже.
i.https://zenn.dev/nemtus/articles/nemtus-symbol-sdk-typescript#samplecode
Бэкграунд
SDK версии 2 блокчейна Symbol для TypeScript/JavaScript устарел, и основная группа разработчиков (core-devs) работает над разработкой и обслуживанием версии 3 SDK для JavaScript, которая проще в работе.
symbol-sdk v 2
symbol-sdk v2 — это SDK для JavaScript/TypeScript, который упростил разработку с использованием блокчейна Symbol, используя богатый набор функций.
Однако из-за различий в предпочтениях в отношении используемых rxjs, сложности богатой функциональности и организационных изменений было принято решение создать новый эталонный SDK, который больше соответствует основному протоколу. Было официально объявлено, что SDK v2 устарел.
symbol-sdk v 3
Новая версии SDK 3 написана на JavaScript, поэтому, если вы попытаетесь использовать ее в среде TypeScript, модуль выдаст ошибку “***”. В современной среде фронтенд-разработки, где язык программирования TypeScript очень популярен, поэтому ситуация не очень хорошая.
Поэтому, чтобы исправить эту ситуацию и попытаться каким-то образом преобразовать SDK в язык программирования в TypeScript, мы рассмотрели следующие 3 метода:
1. Создайте форк symbol-sdk v2 TypeScript SDK и продолжайте поддержку (обслуживание) независимо от разработчиков NEMTUS и разработчиков сообщества.
2. Японская организация NEMTUS и разработчики сообщества внедрят TypeScript SDK и продолжат разработку и обслуживание, ссылаясь на SDK версии 3, для JavaScript.
3. Разветвленная (Форк) версия SDK 3 для JavaScript используется как есть. Затем NEMTUS и разработчики из сообщества Symbol добавят или автоматически сгенерируют необходимые файлы TypeScript «.d.ts», чтобы упростить разработку и обслуживание.
__________
- Хотелось бы отметить что обслуживание зависимых пакетов, является важным сложным моментом в этом вопросе.
- Необходимо иметь точное понимание о том, как транзакции блокчейна NEM/Symbol, должны быть бинаризированы и обработаны в качестве “DSL” (Предметно-ориентированный язык), поэтому вероятно, это займет время и будет очень сложным фактором.
Мы получили совет от независимых разработчиков-добровольцев из сообщества Symbol и решили заняться методом номер 3, который описан выше в этой статье.
Начиная с версии языка программирования TypeScript 3.7 или более поздней, вы можете создать файл «.d.ts» (который описывает синтаксис и структуру функций и свойств) из файлов «.js». Комментарии JSDoc были относительно хорошо написаны в официальном SDK (Software Development Kit), поэтому мы смогли выпустить обновленный SDK, который можно в некоторой степени использовать в среде TypeScript.
Комментарии JSDoc написаны к исходному коду JavaScript и используются инструментами разработки для предоставления разработчикам соответствующих подсказок и дополнений, а также для автоматического создания документации.
Как сгенерировать файл d.ts из файла js ?
Подробнее можно ознакомиться в следующей статье:
Пример кода для отправки транзакции с использованием @nemtus/symbol-sdk-typescript
Установка
- Установите Node.js (Если вы это сделали, тогда пропустите этот шаг).
- Создайте соответствующий каталог (в качестве примера здесь symbol-sdk-typescript-sample-1) и инициализируйте.
<!-- wp:paragraph -->
<p>~/$ mkdir symbol-sdk-typescript-sample-1</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>~/$ cd symbol-sdk-typescript-sample-1</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>~/symbol-sdk-typescript-sample-1$ npm init -y</p>
<!-- /wp:paragraph -->
Установите необходимые пакеты
В этом примере мы будем использовать следующие пакеты для инициализации транзакций:
- typescript, ts-node… Язык программирования Typescript используется, для выполнения различных действий, позволяя (более полно описывать свойства и методы объектов и классов в Typescript), а ts-node необходим, для удобства выполнения этих задач.
- С помощью REST API, можно получать информацию о блокчейне Symbol, а также реализовать отправку транзакции и многое другое. @nemtus/symbol-sdk-openapi-generator-typescript-axios
- Комплект для разработки программного обеспечения (SDK) для TypeScript, созданный на этот раз (обработка информации об аккаунте, создание данных транзакции, подписание и т. д.). @nemtus/symbol-sdk-typescript
- Для использования веб-сокетов. ws
- Для использования REST API клиента. Axios
- Для обработки приватного ключа в качестве переменной среды и при этом не записывать приватный ключ в исходный код. dotenv
Необходимо выполнить следующую команду:
<!-- wp:paragraph -->
<p><em>~/symbol-sdk-typescript-sample-1$ npm install -D typescript ts-node @types/ws</em></p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><em>~/symbol-sdk-typescript-sample-1$ npm install @nemtus/symbol-sdk-typescript @nemtus/symbol-sdk-openapi-generator-typescript-axios axios ws dotenv</em></p>
<!-- /wp:paragraph -->
Создайте файл tsconfig.json
Выполните следующую команду, чтобы сгенерировать шаблон файла конфигурации tsconfig.json, для компиляции кода на TypeScript.
~/symbol-sdk-typescript-sample-1$ npx tsc --init
Измените «target»: «es2016» на «target»: «esnext», чтобы вы могли использовать более новый стиль написания для JavaScript, такой как модули ES и BigInt
BigInt позволяет разработчикам иметь гораздо лучшее целочисленное представление и обработку данных для дальнейшей работы с этими данными, а ES добавляет в JavaScript официальную унифицированную модульную систему.
Создание тестового аккаунта и установка переменной среды
Загрузите официальный блокчейн-кошелек Symbol, создайте тестовый аккаунт в тестовой сети и получите тестовые токены в Symbol Faucet 👉
https://testnet.symbol.tools . Затем сохраните свой приватный, публичный ключ, а также адрес своего кошелька.
Поэтому давайте добавим приватный ключ в файл .env следующим образом.
.env
SIGNER_1_PRIVATE_KEY =”PUT_YOUR_PRIVATE_KEY_HERE”
⚠️ В блокчейне приватный ключ имеет наибольшую и единственную возможность что-либо сделать с вашей крипто-учетной записью. Приватный ключ обеспечивает доступ к вашему крипто-аккаунту и позволяет управлять им и его следует держать в секрете. Если ваш приватный ключ будет скомпрометирован, вы потеряете все свои активы и конфиденциальную информацию в вашего аккаунта. На этот раз, мы создадим одноразовый аккаунт в тестовой сети Symbol и попробуем, использовать приватный ключ в виде простой переменной среды с помощью dotenv.
Модуль dotenv анализирует файл «.env» и делает установленные в нем переменные доступными из переменных среды.
Образец кода
Давайте создадим следующий файл и запустите его с помощью npx ts-node send-transfer-transaction.ts.
send-transfer-tx.ts
import { SymbolFacade } from "@nemtus/symbol-sdk-typescript/esm/facade/SymbolFacade";
import { PrivateKey } from "@nemtus/symbol-sdk-typescript/esm/CryptoTypes";
import { KeyPair } from "@nemtus/symbol-sdk-typescript/esm/symbol/KeyPair";
import { Signature } from "@nemtus/symbol-sdk-typescript/esm/symbol/models";
import {
Configuration,
NetworkRoutesApi,
TransactionGroupEnum,
TransactionRoutesApi,
TransactionStatusDTO,
TransactionStatusRoutesApi,
} from "@nemtus/symbol-sdk-openapi-generator-typescript-axios";
import WebSocket from "ws";
import "dotenv/config";
// Укажите узел в тестовой сети
const NODE_DOMAIN = "symbol-test.next-web-technology.com";
// Адрес назначения... На этот раз мы отправим его обратно на адрес Faucet.
const faucetAddressString = "TDMYLKCTEVPSRPTG4UXW47IQPCYNLW2OVWZMLGY";
(async () => {
// Вызовите NetworkRoutesApi.getNetworkProperties, чтобы получить epochAdjustment, networkCurrencyMosaicId
const configurationParameters = {
basePath: `http://${NODE_DOMAIN}:3000`,
};
const configuration = new Configuration(configurationParameters);
const networkRoutesApi = new NetworkRoutesApi(configuration);
const networkPropertiesDTO = (await networkRoutesApi.getNetworkProperties())
.data;
// Поскольку значение ответа epochAdjustment представляет собой строку и содержит s в конце, удалите его и преобразуйте в число.
const epochAdjustmentOriginal = networkPropertiesDTO.network.epochAdjustment!;
const epochAdjustment = parseInt(epochAdjustmentOriginal.replace(/s/g, ""));
// Поскольку ответное значение networkCurrencyMosaicId представляет собой шестнадцатеричную строку и содержит ' в середине, удалите ее и преобразуйте в BigInt.
const networkCurrencyMosaicIdOriginal =
networkPropertiesDTO.chain.currencyMosaicId!;
const networkCurrencyMosaicId = BigInt(
networkCurrencyMosaicIdOriginal.replace(/'/g, "")
);
// Сделайте Вызов NetworkRoutesApi.getNetworkType, чтобы получить имя сети, такое как testnet, указанное в фасаде.
const networkTypeDTO = (await networkRoutesApi.getNetworkType()).data!;
const networkName = networkTypeDTO.name;
// Необходимо инициализировать SDK с сетевым именем
const facade = new SymbolFacade(networkName);
// Создание данных, связанных с учетной записью, для отправки транзакций
const signer1PrivateKeyString = process.env.SIGNER_1_PRIVATE_KEY!;
const signer1PrivateKey = new PrivateKey(signer1PrivateKeyString);
const signer1KeyPair = new KeyPair(signer1PrivateKey);
const signer1PublicKeyString = signer1KeyPair.publicKey.toString();
const signer1AddressString = facade.network
.publicKeyToAddress(signer1KeyPair.publicKey)
.toString();
// Расчет крайнего срока (установлен на 2 часа, но может быть изменен, но произойдет ошибка, если он будет слишком большим)
const now = Date.now();
const deadline = BigInt(now - epochAdjustment * 1000 + 2 * 60 * 60 * 1000);
// Сгенерировать данные транзакции... (Пример) Отправить 1XYM = 1000000μXYM от SIGNER_1 на FAUCET
const transaction = facade.transactionFactory.create({
type: "transfer_transaction",
signerPublicKey: signer1PublicKeyString,
deadline,
recipientAddress: faucetAddressString,
mosaics: [{ mosaicId: networkCurrencyMosaicId, amount: 1000000n }],
});
// Настройка оплаты ... Это зависит от настройки узла назначения, но я думаю, что значение настройки по умолчанию 100 для узла в основном достаточно.
const feeMultiplier = 100;
(transaction as any).fee.value = BigInt(
(transaction as any).size * feeMultiplier
);
//подпись
const signature = facade.signTransaction(signer1KeyPair, transaction);
(transaction as any).signature = new Signature(signature.bytes);
// Установите для каждой сети конкретное поколение HashSeed
(transaction as any).network.generationHashSeed = facade.network;
// Вычислить хэш транзакции ... Необходимо при последующем подтверждении статуса утверждения транзакции с помощью WebSocket
const hash = facade.hashTransaction(transaction);
console.log(hash.toString());
console.log(`https://testnet.symbol.fyi/transactions/${hash.toString()}`); // Отображение соответствующей страницы обозревателя блоков, чтобы ее было легко проверить при отладке
// Используйте эти данные при отправке транзакций
const transactionPayload = (
facade.transactionFactory.constructor as any
).attachSignature(transaction, signature);
// 1 Настройки для случаев, отличных от подтверждения
const confirmationHeight = 6; // 6confで確認と見なす場合
let transactionHeight = 0;
let blockHeight = 0;
let finalizedBlockHeight = 0;
//Необходимо предопределить обработку по различным событиям при отправке транзакций с WebSocket
const ws = new WebSocket(`wss://${NODE_DOMAIN}:3001/ws`);
ws.on("open", () => {
console.log("connection open");
});
ws.on("close", () => {
console.log("connection closed");
});
ws.on("message", async (msg: any) => {
const res = JSON.parse(msg);
if ("uid" in res) {
console.log(`uid : ${res.uid}`);
// Отслеживайте, когда транзакция целевого адреса переходит в неподтвержденное состояние
const unconfirmedBody = `{"uid": "${res.uid}", "subscribe": "unconfirmedAdded/${signer1AddressString}"}`;
console.log(unconfirmedBody);
ws.send(unconfirmedBody);
// Мониторинг одобренных транзакций по целевому адресу
const confirmedBody = `{"uid": "${res.uid}", "subscribe": "confirmedAdded/${signer1AddressString}"}`;
console.log(confirmedBody);
ws.send(confirmedBody);
// Мониторинг ошибки транзакции целевого адреса
const statusBody = `{"uid": "${res.uid}", "subscribe": "status/${signer1AddressString}"}`;
console.log(statusBody);
ws.send(statusBody);
// Следите за новыми блоками
const blockBody = `{"uid": "${res.uid}", "subscribe": "block"}`;
console.log(blockBody);
ws.send(blockBody);
// Смотреть готовые блоки
const finalizedBlockBody = `{"uid": "${res.uid}", "subscribe": "finalizedBlock"}`;
console.log(finalizedBlockBody);
ws.send(finalizedBlockBody);
}
// Запускается, когда транзакция не подтверждена
if (
res.topic === `unconfirmedAdded/${signer1AddressString}` &&
res.data.meta.hash === hash.toString()
) {
console.log("transaction unconfirmed");
}
// Запускается, когда транзакция одобрена
if (
res.topic === `confirmedAdded/${signer1AddressString}` &&
res.data.meta.hash === hash.toString()
) {
console.log("transaction confirmed");
transactionHeight = parseInt(res.data.meta.height);
}
// Срабатывает при создании блока
if (res.topic === `block`) {
console.log("block");
blockHeight = parseInt(res.data.block.height);
}
// Срабатывает, когда блок завершен
if (res.topic === `finalizedBlock`) {
console.log("finalizedBlock");
console.log(res);
finalizedBlockHeight = parseInt(res.data.height);
}
// Запускается при сбое транзакции
if (
res.topic === `status/${signer1AddressString}` &&
res.data.hash === hash.toString()
) {
console.log(res.data.code);
ws.close();
} else {
console.log(res);
}
// confirmationHeightブロック後に監視終了
if (
transactionHeight !== 0 &&
transactionHeight + confirmationHeight - 1 <= blockHeight
) {
console.log(
`${confirmationHeight} blocks confirmed. transactionHeight is ${transactionHeight} blockHeight is ${blockHeight}.`
);
// Проверить статус транзакции и завершить мониторинг
try {
const transactionStatusRoutesApi = new TransactionStatusRoutesApi(
configuration
);
const transactionStatusDTO: TransactionStatusDTO = (
await transactionStatusRoutesApi.getTransactionStatus({
hash: hash.toString(),
})
).data;
if (transactionStatusDTO.group === TransactionGroupEnum.Confirmed) {
// Обработка подтверждения транзакции здесь
ws.close();
} else if (
transactionStatusDTO.group === TransactionGroupEnum.Unconfirmed
) {
// Если он снова становится неутвержденным, продолжайте отслеживать как есть.
console.log("rollback detected. transaction is unconfirmed.");
} else {
// Напишите сюда обработку, когда транзакция исчезает без одобрения... Например, проверить статус и повторно объявить и т.д.
console.log("rollback detected. transaction disappeared.");
ws.close();
}
} catch (err) {
console.error(err);
ws.close();
}
} else {
console.log(
`wait for ${confirmationHeight} blocks. transactionHeight is ${transactionHeight} blockHeight is ${blockHeight}.`
);
}
// Мониторинг заканчивается после того, как finalizedBlockHeight проходит целевой блок
if (transactionHeight !== 0 && transactionHeight <= finalizedBlockHeight) {
console.log(
`${finalizedBlockHeight} block finalized. transactionHeight is ${transactionHeight} blockHeight is ${blockHeight}.`
);
// Проверить статус транзакции и завершить мониторинг
try {
const transactionStatusRoutesApi = new TransactionStatusRoutesApi(
configuration
);
const transactionStatusDTO: TransactionStatusDTO = (
await transactionStatusRoutesApi.getTransactionStatus({
hash: hash.toString(),
})
).data;
if (transactionStatusDTO.group === TransactionGroupEnum.Confirmed) {
// Обработка подтверждения транзакции здесь
ws.close();
} else if (
transactionStatusDTO.group === TransactionGroupEnum.Unconfirmed
) {
// Обработка подтверждения транзакции здесь
console.log("rollback detected. transaction is unconfirmed.");
} else {
// Напишите сюда обработку, когда транзакция исчезает без одобрения... Например, проверить статус и повторно объявить и т.д.
console.log("rollback detected. transaction disappeared.");
ws.close();
}
} catch (err) {
console.error(err);
ws.close();
}
} else {
console.log(
`wait for finalized block. transactionHeight is ${transactionHeight} blockHeight is ${blockHeight}.`
);
}
});
// Объявление транзакций
try {
const transactionRoutesApi = new TransactionRoutesApi(configuration);
console.log(transactionPayload);
const response = await transactionRoutesApi.announceTransaction({
transactionPayload,
});
console.log(response.data);
} catch (err) {
console.error(err);
}
})();
При инициализации такой транзакции, если вы откроете кошелек, транзакция будет отправлена и вы услышите звук «цзин». В коде примера написано большое количество комментариев, чтобы вы могли видеть, где и что вы делаете. Если у вас есть какие-либо проблемы, не стесняйтесь обращаться к нашему GitHub или Discord.
Пример журнала времени выполнения (log)
~/symbol-sdk-typescript-sample-1$ npx ts-node send-transfer-transaction.ts
40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F
https://testnet.symbol.fyi/transactions/40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F
{"payload": "B00000000000000008B788D279A618F169687225327E5721D0D6A2738F10F53A82347310E6CCD4928AA6C8705E6219BCE50E76D1BD5D499567C97E2390C6398689DEFE60EB90A506ECF3FF68E017A83528A0A361F1F1EE91D761B5E34008AD9474870D54F5C4D0680000000001985441C044000000000000F64B73920500000098D985A853255F28BE66E52F6E7D1078B0D5DB4EADB2C59B0000010000000000C8B6532DDB16843A40420F0000000000"}
{ message: 'packet 9 was pushed to the network via /transactions' }
connection open
uid : PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL
{"uid": "PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL", "subscribe": "unconfirmedAdded/TBFVGBN5XKVFWF3PKWRQRPH6SHSOTXJMXKYSTEQ"}
{"uid": "PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL", "subscribe": "confirmedAdded/TBFVGBN5XKVFWF3PKWRQRPH6SHSOTXJMXKYSTEQ"}
{"uid": "PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL", "subscribe": "status/TBFVGBN5XKVFWF3PKWRQRPH6SHSOTXJMXKYSTEQ"}
{"uid": "PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL", "subscribe": "block"}
{"uid": "PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL", "subscribe": "finalizedBlock"}
{ uid: 'PE56L7DT7UFEV4ZUZM6JEB373PJNCLUL' }
wait for 6 blocks. transactionHeight is 0 blockHeight is 0.
wait for finalized block. transactionHeight is 0 blockHeight is 0.
transaction unconfirmed
{
topic: 'unconfirmedAdded/TBFVGBN5XKVFWF3PKWRQRPH6SHSOTXJMXKYSTEQ',
data: {
transaction: {
signature: '08B788D279A618F169687225327E5721D0D6A2738F10F53A82347310E6CCD4928AA6C8705E6219BCE50E76D1BD5D499567C97E2390C6398689DEFE60EB90A506',
signerPublicKey: 'ECF3FF68E017A83528A0A361F1F1EE91D761B5E34008AD9474870D54F5C4D068',
version: 1,
network: 152,
type: 16724,
maxFee: '17600',
deadline: '23931866102',
recipientAddress: '98D985A853255F28BE66E52F6E7D1078B0D5DB4EADB2C59B',
mosaics: [Array]
},
meta: {
hash: '40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F',
merkleComponentHash: '40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F',
height: '0'
}
}
}
wait for 6 blocks. transactionHeight is 0 blockHeight is 0.
wait for finalized block. transactionHeight is 0 blockHeight is 0.
block
{
topic: 'block',
data: {
block: {
signature: '27C609DDBD9E552425B736A1222B32C2E1ABD9431E4B59FD68705460799F4A95E5B39625D7461A7F780DF1108E85B80D37EF966D34567CE1342C8D273DF27D05',
signerPublicKey: 'CD96C6830906530C4BCD7C45453F5D55A5FA5BAF098CFC4E512B18CC763D9573',
version: 1,
network: 152,
type: 33091,
height: '653699',
timestamp: '23924697359',
difficulty: '10000000000000',
proofGamma: '14987781C5471F99EE0A168007E8F1E0AF204FC351057178071B73D9923CD4B3',
proofVerificationHash: '5A494A1E9335148507B7C58162249217',
proofScalar: 'A086226451E081BABC25619348E2FC5026F2688C0742D375B66F73BF580B6E02',
previousBlockHash: 'C6DF5E1406BF16CB0FBD421AE524016E2FD16DFF1AF56D72F2AF0B871A908E21',
transactionsHash: '40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F',
receiptsHash: '0E12701813430073FDFA2E524C5AA182950DB5C2931FB0A015D260D6A54939C3',
stateHash: '978B0BCAC574548EF5C28F15F6791ACAAE40A16A326C9C236D041335981E5B1D',
beneficiaryAddress: '980F30859E6AB05706FD93188B39A42B42A44AC8DA115053',
feeMultiplier: 100
},
meta: {
hash: '5B09B4DC5B58B277FB74745FF5C9483467BE8ECB10FF61384184B5F82EE9C666',
generationHash: 'F8084B2C740931EF6C84430E33B30248E90458AD4EE266111BE797E7AD1C5329'
}
}
}
wait for 6 blocks. transactionHeight is 0 blockHeight is 653699.
wait for finalized block. transactionHeight is 0 blockHeight is 653699.
transaction confirmed
{
topic: 'confirmedAdded/TBFVGBN5XKVFWF3PKWRQRPH6SHSOTXJMXKYSTEQ',
data: {
transaction: {
signature: '08B788D279A618F169687225327E5721D0D6A2738F10F53A82347310E6CCD4928AA6C8705E6219BCE50E76D1BD5D499567C97E2390C6398689DEFE60EB90A506',
signerPublicKey: 'ECF3FF68E017A83528A0A361F1F1EE91D761B5E34008AD9474870D54F5C4D068',
version: 1,
network: 152,
type: 16724,
maxFee: '17600',
deadline: '23931866102',
recipientAddress: '98D985A853255F28BE66E52F6E7D1078B0D5DB4EADB2C59B',
mosaics: [Array]
},
meta: {
hash: '40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F',
merkleComponentHash: '40EED5433899E2EB1FB33A864CCEDB9D7F5F42A59561F1B4341DE3751030B85F',
height: '653699'
}
}
}
wait for 6 blocks. transactionHeight is 653699 blockHeight is 653699.
wait for finalized block. transactionHeight is 653699 blockHeight is 653699.
block
{
topic: 'block',
data: {
block: {
signature: '300C88C9BDDBF04C4F81A80917FE058CFC9458B84E08D509ADF243693D94D27E0098DDC3FB8BA226435ACA4DE9BE95FDC692B0C683F95EF5883CA69193A44906',
signerPublicKey: 'BF2EAFD7C2B1E84C814B797332CA10E82CC3E3C1E7BC8ACC4640E7FD33C90A2C',
version: 1,
network: 152,
type: 33091,
height: '653700',
timestamp: '23924741192',
difficulty: '10000000000000',
proofGamma: '0953D5657183B9F500871FDF9BB83EDCDBF5D9B931BF32D1783FD9BCDC38F1A2',
proofVerificationHash: 'A5192E49F1E794737D3C831D5585B401',
proofScalar: 'DF1929D97CD80E0F0C085524840F0009FBCAF1683AE86B77E55C03DD2561FA0F',
previousBlockHash: '5B09B4DC5B58B277FB74745FF5C9483467BE8ECB10FF61384184B5F82EE9C666',
transactionsHash: '0000000000000000000000000000000000000000000000000000000000000000',
receiptsHash: '55917278DD7CA2D0BAEF12D5DD072CC929A2187AAC78E239E043A1F4198AC5DF',
stateHash: '2FB6BE644C3CC1186CD737C39E14EDB24D90DBEEF87DF779136F88AA2C9003D7',
beneficiaryAddress: '985F693ED8D58BC10F3E428E600E17F704BE042B03198B2A',
feeMultiplier: 0
},
meta: {
hash: 'D36D50647F1F41EA75FAB503F8F0795F5762C2198268EC9FB4F4013D577F7815',
generationHash: 'D67B01773A8B6BC9E2FF7BBB0423DB4D8C843478B4556391062512687CC42DCE'
}
}
}
wait for 6 blocks. transactionHeight is 653699 blockHeight is 653700.
wait for finalized block. transactionHeight is 653699 blockHeight is 653700.
block
{
topic: 'block',
data: {
block: {
signature: '64B0A8BAFA35F1D2A7F8D00475D4ACB8BA3AC546CB3445BA190A123A706CCADFC89B102396BABDA49803298B987206F49C97164DACBEDAFE63DA430954923800',
signerPublicKey: '21CF6E21A73CB4CEBD32BA0AE2C7059D19B1A7827DF6C8D10FF33C3F1A2BF0E8',
version: 1,
network: 152,
type: 33091,
height: '653701',
timestamp: '23924771171',
difficulty: '10000000000000',
proofGamma: '414F99CCF2115DC10CF761D3D4E335884ADCA8A74D9479FD67EAF38D61915D12',
proofVerificationHash: '523DF3CEE73CA1F1684EF22599BF8B58',
proofScalar: 'FE12167FE39A1EEA8FFD7B18D35F847B1D42BE696EA16534D9F669A0910A270C',
previousBlockHash: 'D36D50647F1F41EA75FAB503F8F0795F5762C2198268EC9FB4F4013D577F7815',
transactionsHash: '0000000000000000000000000000000000000000000000000000000000000000',
receiptsHash: 'BFC94F3C268EA1D531DEE62CCF388CCB85746D368DAC775171A904B5897C0566',
stateHash: 'B199DE8B7A60975EE9549075FF821F83289196564FF0A52C5354BDEC138D5DD2',
beneficiaryAddress: '98FFA418508A3B022EF3491FC8254DEB7EC3EBA65B52DE1D',
feeMultiplier: 0
},
meta: {
hash: '0D5F10306D3F7E63158E1581C96EB1D636BD7787FACE35CADCD1D8A8E2AA7D1D',
generationHash: 'F8210DAC0163CB037F3ABC73E59FE86C070DDC827E5922AAB4208FCE7666F824'
}
}
}
wait for 6 blocks. transactionHeight is 653699 blockHeight is 653701.
wait for finalized block. transactionHeight is 653699 blockHeight is 653701.
block
{
topic: 'block',
data: {
block: {
signature: '12118E9565A88F932FE89D3595E01EE991CB4A803F375D9A1CCEF0D667C9C180F4F1DB8A6438C3626BF87E9278FA0601B88EF03DA807DE9C4220BA92A926D002',
signerPublicKey: 'BF2EAFD7C2B1E84C814B797332CA10E82CC3E3C1E7BC8ACC4640E7FD33C90A2C',
version: 1,
network: 152,
type: 33091,
height: '653702',
timestamp: '23924792232',
difficulty: '10000000000000',
proofGamma: 'B6B4EAFCAC77DFBFE42BEC7BC41E9B1D65C0A27EEE97E94F55AB08E9FF9910D9',
proofVerificationHash: 'A8A8244A0EB6AC01E18A228DC44865E7',
proofScalar: '67147B2A8C4B73F8CF31E98CE48DB95A76CF0DD9C24F3AF23094A86D5CCE930D',
previousBlockHash: '0D5F10306D3F7E63158E1581C96EB1D636BD7787FACE35CADCD1D8A8E2AA7D1D',
transactionsHash: '0000000000000000000000000000000000000000000000000000000000000000',
receiptsHash: '55917278DD7CA2D0BAEF12D5DD072CC929A2187AAC78E239E043A1F4198AC5DF',
stateHash: 'DCE2463E6D9D10F758F1904718539329890DE030447C37511910C50DF1D34A34',
beneficiaryAddress: '985F693ED8D58BC10F3E428E600E17F704BE042B03198B2A',
feeMultiplier: 0
},
meta: {
hash: 'CC4DF75939F1ED540890EA97688055CC686AA9B2D1FA1998A82B05FF094E35FA',
generationHash: 'FDB798D4ACBCC9B60F4A35BCD9F5D80152909D51B5FF9A7236DD7BF0325D1723'
}
}
}
wait for 6 blocks. transactionHeight is 653699 blockHeight is 653702.
wait for finalized block. transactionHeight is 653699 blockHeight is 653702.
block
{
topic: 'block',
data: {
block: {
signature: '48011E2F4DE712B135B59FE782375730882B01D8D66B5A01BAB0B89D05E66673EDEF24E25B609835E54D1D3957E942C1BF620988DF231F44AEA0810557433A08',
signerPublicKey: 'F9A5A66EBE9AD5EAAAF07AF208BF33FB0B24C2049EFF99B65AD1BB46809852DE',
version: 1,
network: 152,
type: 33091,
height: '653703',
timestamp: '23924824521',
difficulty: '10000000000000',
proofGamma: 'D0E1CDB0F05EF355CB4C3150233A6F69063F0F1641DAA48A2710136909857B01',
proofVerificationHash: 'A5755D01A57F5CE9305FFF84DAEAFB5B',
proofScalar: 'F4167D2CAC137C7E8B50F0C3786E012F191CB7CEFF6E85A9999F0F9B2432320C',
previousBlockHash: 'CC4DF75939F1ED540890EA97688055CC686AA9B2D1FA1998A82B05FF094E35FA',
transactionsHash: '0000000000000000000000000000000000000000000000000000000000000000',
receiptsHash: 'F426FEC961E15E6F1A76117DA8363DE4064391816B024B5134F6BA19DCAF5DC0',
stateHash: 'DF1C0EEEAACA2E966B3ECA891234482315C7057C1628E5C0CBECBD91D0ABCEF7',
beneficiaryAddress: '98D3970759CB13CD9E6BD7FBEBD7F909F34ADA4E079B1A4D',
feeMultiplier: 0
},
meta: {
hash: '661392D9004B85260818CF03AA16AF05F987EB7ED700DB37D574059E258BB3CE',
generationHash: 'F473AEDD8F5183A4C497ADA2C4F7798B73C06BF7DAB6D6E5C19628A267913F9A'
}
}
}
wait for 6 blocks. transactionHeight is 653699 blockHeight is 653703.
wait for finalized block. transactionHeight is 653699 blockHeight is 653703.
block
{
topic: 'block',
data: {
block: {
signature: '43417AF8B7CEDC9D359EF4B17745523968EF0287F835C8D5A758E919B53970B11FC2894E1953185E577FA6B442982FE051719EBAE8B9A2771FC36DACC213940E',
signerPublicKey: '88A7993C2478345E3B86A98A2D8AC47739F7A95620238018958E3961C153E263',
version: 1,
network: 152,
type: 33091,
height: '653704',
timestamp: '23924861796',
difficulty: '10000000000000',
proofGamma: '60F4CA9CD7AFBD3F5BE8ED42A40B5CE3A90F2EAD4969F0F719A12516F24D67D6',
proofVerificationHash: '525BB53255B1A900B29D85E3564E56F3',
proofScalar: '8214A6B61FD2BD2FE53F465DAEC6E3B2540B62EBACF083E92D6A323D78B03A03',
previousBlockHash: '661392D9004B85260818CF03AA16AF05F987EB7ED700DB37D574059E258BB3CE',
transactionsHash: '0000000000000000000000000000000000000000000000000000000000000000',
receiptsHash: '987E011A37AC36B4D5524D846515B7580B33B41360083578BD721C85D07AD753',
stateHash: 'A7E06767E5BDD277A82F472000E18038E5BAEDACB87CCE28F186BAED438BA0CE',
beneficiaryAddress: '98258E9856A612C5346D3C0B318DCB654257BD9DD86E6481',
feeMultiplier: 0
},
meta: {
hash: '2DB314AD386B94F413F627A0370D175E846A572CD3D62DBF92175166437AC3ED',
generationHash: 'F49E42593C78FCE7FBE9D211F3AAA4DED5E8EBCDE82F1613B54D41D93AD62A1E'
}
}
}
6 blocks confirmed. transactionHeight is 653699 blockHeight is 653704.
wait for finalized block. transactionHeight is 653699 blockHeight is 653704.
connection closed
Резюме
Теперь, когда у нас есть клиент TypeScript REST API и npm-пакет TypeScript (для отправки транзакций), мы можем начать фронтенд-разработку в среде TypeScript, используя инструменты, соответствующие концепции нового официального SDK.
Однако если вы посмотрите на пример кода, то увидите, что есть места, где проблем можно избежать с помощью некоторых обходных путей. Таким образом, некоторые части кода могут быть улучшены путем написания комментариев в комментариях JSDoc (они помогут улучшить файлы определения типов, автоматически сгенерированные), поэтому, если я могу, я хочу отправить запрос на извлечение, чтобы улучшить их напрямую. к новому официальному SDK Symbol.
С момента запуска Symbol прошло около полутора лет, но еще много неизвестного о том, как будет развиваться экосистема Symbol и NEM. Также на данный момент не известно, какое место в экосистеме Symbol займут SDK от NEMTUS. (Может быть будет другой SDK, лучший, чем этот и это было бы здорово).
- @nemtus/symbol-sdk-openapi-generator-typescript-axios
- @nemtus/symbol-sdk-openapi-generator-typescript-fetch
- @nemtus/symbol-sdk-typescript
Про NEMTUS
Если у вас есть что добавить к статьям от NEMTUS, связанных с NEM или Symbol или SDK, пожалуйста, не стесняйтесь сотрудничать с нами. Мы будем очень признательны за это.
Японская некоммерческая организация NEMTUS, будет рада продолжать улучшать техническую информацию о NEM и Symbol и вносить свой вклад в экосистему.
Автор Статьи
Имя Автора: Ясунори Мацуока (松岡靖典)
Организация: NEMTUS
Биография:
- Принимал участие в веб-разработке блокчейна в CauchyE Co., Ltd.
- С августа 2022 года Ясунори работает на постоянной основе в качестве заместителя председателя некоммерческой организации NEMTUS по продвижению технологии блокчейна NEM/Symbol.
Социальные сети:
Твиттер: https://twitter.com/salaryman_tousi
GitHub: https://github.com/YasunoriMATSUOKA
___
Перевод: SymbolTimes