rebrand(lethean): update branding, ports, and config for Lethean blockchain
Some checks failed
Publish lethean-utils-js / build-and-publish (push) Failing after 57s
Some checks failed
Publish lethean-utils-js / build-and-publish (push) Failing after 57s
- Coin: Zano → Lethean, ticker: ZAN/ZANO → LTHN - Ports: 11211 → 36941 (mainnet RPC), 46941 (testnet RPC) - Wallet: 11212 → 36944/46944 - Address prefix: iTHN - URLs: zano.org → lethean.io - Explorer links: explorer.lthn.io Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b69407351c
commit
0bb6edf8f1
21 changed files with 10392 additions and 951 deletions
2
.github/workflows/npm-publish.yml
vendored
2
.github/workflows/npm-publish.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Publish zano-utils-js to zano-project
|
||||
name: Publish lethean-utils-js
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
|
|||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Build-only: compiles the TypeScript crypto library to dist/
|
||||
FROM node:22-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
RUN yarn build
|
||||
|
||||
# Minimal image with the compiled library
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/package.json ./
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Zano Team
|
||||
Copyright (c) 2025 Lethean Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
76
README.md
76
README.md
|
|
@ -1,7 +1,7 @@
|
|||
# zano-utils-js
|
||||
Set of helpers and tools for JS developers that working with Zano
|
||||
# lethean-utils-js
|
||||
Set of helpers and tools for JS developers working with the Lethean blockchain.
|
||||
<!-- TOC -->
|
||||
* [Zano Utils JS](#zano-utils-js)
|
||||
* [Lethean Utils JS](#lethean-utils-js)
|
||||
* [Blockchain Description](#blockchain-description)
|
||||
* [Functions](#functions)
|
||||
* [decodeTransaction](#decodetransaction)
|
||||
|
|
@ -32,8 +32,8 @@ Set of helpers and tools for JS developers that working with Zano
|
|||
|
||||
## Blockchain Description
|
||||
|
||||
- **Ticker**: Zano
|
||||
- **Network**: Zano
|
||||
- **Ticker**: LTHN
|
||||
- **Network**: Lethean
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ Set of helpers and tools for JS developers that working with Zano
|
|||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{ "jsonrpc": "2.0", "method": "get_tx_details", "params": {"tx_hash": "77b09d759fefd512642f9a5e4e31ed0fefbaf1a8e602a2be94fc511ff982f7cf" }, "id": 1 }' \
|
||||
"http://37.27.100.59:10500/json_rpc"
|
||||
"http://127.0.0.1:36941/json_rpc"
|
||||
```
|
||||
|
||||
<details>
|
||||
|
|
@ -144,8 +144,8 @@ You can prodive integrated address or master address.
|
|||
#### Import and usage
|
||||
|
||||
```ts
|
||||
import { decodeTransaction } from '@zano-project/zano-utils-js';
|
||||
import type { DecodeTransactionResult } from '@zano-project/zano-utils-js';
|
||||
import { decodeTransaction } from '@aspect-build/lethean-utils-js';
|
||||
import type { DecodeTransactionResult } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
decodeTransaction(objectInJson, secretViewKey, address);
|
||||
// or provide public spend key
|
||||
|
|
@ -162,13 +162,13 @@ type DecodeTransactionResult =
|
|||
|
||||
### `txUtils`
|
||||
|
||||
Namespace that provides low-level cryptographic and transaction-related helper functions for Zano transactions.
|
||||
Namespace that provides low-level cryptographic and transaction-related helper functions for Lethean transactions.
|
||||
These utilities allow working with transaction outputs, stealth addresses, key images, and encrypted fields.
|
||||
|
||||
Import utils:
|
||||
|
||||
```ts
|
||||
import { txUtils } from '@zano-project/zano-utils-js';
|
||||
import { txUtils } from '@aspect-build/lethean-utils-js';
|
||||
```
|
||||
|
||||
#### `getConcealingPoint`
|
||||
|
|
@ -245,8 +245,8 @@ parseObjectInJson(objectInJson: string): TransactionObject | TransactionObjectV3
|
|||
### `generateAccount`
|
||||
|
||||
```typescript
|
||||
import { generateAccount } from '@zano-project/zano-utils-js';
|
||||
import type { AccountResult } from '@zano-project/zano-utils-js';
|
||||
import { generateAccount } from '@aspect-build/lethean-utils-js';
|
||||
import type { AccountResult } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const account: AccountResult = generateAccount();
|
||||
```
|
||||
|
|
@ -270,10 +270,10 @@ type AccountKeys = {
|
|||
### `validateAccount`
|
||||
|
||||
```ts
|
||||
import { validateAccount } from '@zano-project/zano-utils-js';
|
||||
import { validateAccount } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const validatedAccount: boolean = validateAccount(
|
||||
'ZxC15vh38qHAZbfsUXTpxoiyeLhavbBzsQQk81fEwP4jYxN4qR8SEhMfXkRBpQw6vbbSEGpK2VPVPADnL6h3ZViL29Remh4oH',
|
||||
'iTHNLmFJabSdqSdpjs6QkSRFVTkDgsQWMCTzMYZM7QuRKrnEumCNE3PbwbDtVVRwroSZPjx98wx7ZLmqY1LzWYuE2j43qDr11t',
|
||||
'21dcd98fb9dc392aeabe1d5cfb90faf63840685762448bf49a48d58d0c70bf0b',
|
||||
'2ff9e77456d0e65b50d80392a098cddf9032744bd876371fffe95476a92d8564',
|
||||
'88609e3bc954fe8b5f1a5f0a7e7e44528835b62890de49000033b28898888d01',
|
||||
|
|
@ -297,8 +297,8 @@ async function validateAccount(
|
|||
### `generateAccountKeys`
|
||||
|
||||
```ts
|
||||
import { generateAccountKeys } from '@zano-project/zano-utils-js';
|
||||
import type { AccountKeys } from '@zano-project/zano-utils-js';
|
||||
import { generateAccountKeys } from '@aspect-build/lethean-utils-js';
|
||||
import type { AccountKeys } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const accountKeys: AccountKeys = generateAccountKeys();
|
||||
```
|
||||
|
|
@ -317,7 +317,7 @@ type AccountKeys = {
|
|||
### `privateKeyToPublicKey`
|
||||
|
||||
```ts
|
||||
import { privateKeyToPublicKey } from '@zano-project/zano-utils-js';
|
||||
import { privateKeyToPublicKey } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const publicKey: string = privateKeyToPublicKey('88609e3bc954fe8b5f1a5f0a7e7e44528835b62890de49000033b28898888d01');
|
||||
```
|
||||
|
|
@ -326,8 +326,8 @@ const publicKey: string = privateKeyToPublicKey('88609e3bc954fe8b5f1a5f0a7e7e445
|
|||
### `getAccountBySecretSpendKey`
|
||||
|
||||
```ts
|
||||
import { getAccountBySecretSpendKey } from '@zano-project/zano-utils-js';
|
||||
import type { AccountKeys } from '@zano-project/zano-utils-js';
|
||||
import { getAccountBySecretSpendKey } from '@aspect-build/lethean-utils-js';
|
||||
import type { AccountKeys } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const accountKeys: AccountKeys = getAccountBySecretSpendKey('88609e3bc954fe8b5f1a5f0a7e7e44528835b62890de49000033b28898888d01');
|
||||
```
|
||||
|
|
@ -347,8 +347,8 @@ type AccountKeys = {
|
|||
### `getKeyPair`
|
||||
|
||||
```ts
|
||||
import { getKeyPair } from '@zano-project/zano-utils-js';
|
||||
import type { KeyPair } from '@zano-project/zano-utils-js';
|
||||
import { getKeyPair } from '@aspect-build/lethean-utils-js';
|
||||
import type { KeyPair } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const keypair: KeyPair = getKeyPair();
|
||||
```
|
||||
|
|
@ -369,18 +369,18 @@ type KeyPair = {
|
|||
The function accepts either the main master address or the integrated address as a parameter.
|
||||
|
||||
```ts
|
||||
import { getIntegratedAddress } from '@zano-project/zano-utils-js';
|
||||
import { getIntegratedAddress } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const integratedAddress: string = getIntegratedAddress('ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH');
|
||||
const integratedAddress: string = getIntegratedAddress('iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi');
|
||||
```
|
||||
---
|
||||
|
||||
### `createIntegratedAddress`
|
||||
|
||||
```ts
|
||||
import { createIntegratedAddress } from '@zano-project/zano-utils-js';
|
||||
import { createIntegratedAddress } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const integratedAddress: string = createIntegratedAddress('ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH', '49c925855b863a25');
|
||||
const integratedAddress: string = createIntegratedAddress('iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi', '49c925855b863a25');
|
||||
```
|
||||
---
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ params:
|
|||
2. viewPublicKey: string
|
||||
|
||||
```ts
|
||||
import { getMasterAddress } from '@zano-project/zano-utils-js';
|
||||
import { getMasterAddress } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const integratedAddress: string = getMasterAddress('9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa', 'a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3');
|
||||
```
|
||||
|
|
@ -405,10 +405,10 @@ params:
|
|||
1. integratedAddress: string,
|
||||
|
||||
```ts
|
||||
import { splitIntegratedAddress } from '@zano-project/zano-utils-js';
|
||||
import type { SplitedIntegratedAddress } from '@zano-project/zano-utils-js';
|
||||
import { splitIntegratedAddress } from '@aspect-build/lethean-utils-js';
|
||||
import type { SplitedIntegratedAddress } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const integratedAddress: SplitedIntegratedAddress = splitIntegratedAddress('iZ2kFmwxRHoaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e47JPoHxGL5UU2D1tpQMg4');
|
||||
const integratedAddress: SplitedIntegratedAddress = splitIntegratedAddress('iTHnVGr7tms9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJQSA6PNs1faBfevEK7');
|
||||
```
|
||||
|
||||
#### Returned data splitIntegratedAddress
|
||||
|
|
@ -428,10 +428,10 @@ params:
|
|||
1. address: string,
|
||||
|
||||
```ts
|
||||
import { getKeysFromAddress } from '@zano-project/zano-utils-js';
|
||||
import type { ZarcanumAddressKeys } from '@zano-project/zano-utils-js';
|
||||
import { getKeysFromAddress } from '@aspect-build/lethean-utils-js';
|
||||
import type { ZarcanumAddressKeys } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const integratedAddress: ZarcanumAddressKeys = getKeysFromAddress('iZ2kFmwxRHoaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e47JPoHxGL5UU2D1tpQMg4');
|
||||
const integratedAddress: ZarcanumAddressKeys = getKeysFromAddress('iTHnVGr7tms9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJQSA6PNs1faBfevEK7');
|
||||
```
|
||||
|
||||
#### Returned data getKeysFromAddress
|
||||
|
|
@ -448,7 +448,7 @@ type ZarcanumAddressKeys = {
|
|||
Descr: generate payment id for creating integrated address
|
||||
|
||||
```ts
|
||||
import { generatePaymentId } from '@zano-project/zano-utils-js';
|
||||
import { generatePaymentId } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const paymentId: string = generatePaymentId();
|
||||
```
|
||||
|
|
@ -466,8 +466,8 @@ const paymentId: string = generatePaymentId();
|
|||
@returns The secret spend key as a hex string, or `false` if parsing failed.
|
||||
|
||||
```ts
|
||||
import { mnemonicToSeed } from '@zano-project/zano-utils-js';
|
||||
import type { MnemonicToSeedResult } from '@zano-project/zano-utils-js';
|
||||
import { mnemonicToSeed } from '@aspect-build/lethean-utils-js';
|
||||
import type { MnemonicToSeedResult } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const secretSpendKey: MnemonicToSeedResult = mnemonicToSeed('bridge passion scale vast speak mud murder own birthday flight always hair especially tickle crowd shatter tickle deserve hopefully bomb join plan darling aunt beneath give');
|
||||
```
|
||||
|
|
@ -492,8 +492,8 @@ type MnemonicToSeedResult = string | false;
|
|||
- **No audit flag support**: The library does not yet support the audit flag feature.
|
||||
|
||||
```ts
|
||||
import { seedToMnemonic } from '@zano-project/zano-utils-js';
|
||||
import type { SeedToMnemonicResult } from '@zano-project/zano-utils-js';
|
||||
import { seedToMnemonic } from '@aspect-build/lethean-utils-js';
|
||||
import type { SeedToMnemonicResult } from '@aspect-build/lethean-utils-js';
|
||||
|
||||
const randomBytes: string = getRandomBytes(64).toString('hex');
|
||||
|
||||
|
|
@ -510,7 +510,7 @@ type SeedToMnemonicResult = string;
|
|||
|
||||
# Supporting project/donations
|
||||
---
|
||||
ZANO @dev <br>
|
||||
LTHN @dev <br>
|
||||
BTC bc1qpa8w8eaehlplfepmnzpd7v9j046899nktxnkxp <br>
|
||||
BCH qqgq078vww5exd9kt3frx6krdyznmp80hcygzlgqzd <br>
|
||||
ETH 0x206c52b78141498e74FF074301ea90888C40c178 <br>
|
||||
|
|
|
|||
9341
package-lock.json
generated
Normal file
9341
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,9 @@
|
|||
{
|
||||
"name": "@zano-project/zano-utils-js",
|
||||
"version": "0.0.4",
|
||||
"repository": "https://github.com/hyle-team/zano-utils-js",
|
||||
"author": "Zano Team",
|
||||
"name": "@aspect-build/lethean-utils-js",
|
||||
"version": "0.1.0",
|
||||
"description": "Cryptographic utilities for the Lethean blockchain (address encoding, transaction decoding, mnemonic seeds)",
|
||||
"repository": "https://forge.lthn.ai/lthn/lethean-utils-js",
|
||||
"author": "Lethean Team",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@ import { ZarcanumAddressKeys } from 'src/decode/types';
|
|||
|
||||
import {
|
||||
PAYMENT_ID_REGEX,
|
||||
ADDRESS_TAG_PREFIX,
|
||||
ADDRESS_FLAG_PREFIX,
|
||||
ADDRESS_PREFIX,
|
||||
INTEGRATED_ADDRESS_PREFIX,
|
||||
BUFFER_INTEGRATED_ADDRESS_LENGTH,
|
||||
INTEGRATED_ADDRESS_REGEX,
|
||||
PAYMENT_ID_LENGTH,
|
||||
INTEGRATED_ADDRESS_FLAG_PREFIX,
|
||||
INTEGRATED_ADDRESS_TAG_PREFIX,
|
||||
BUFFER_ADDRESS_LENGTH,
|
||||
CHECKSUM_LENGTH,
|
||||
FLAG_LENGTH,
|
||||
SPEND_KEY_LENGTH,
|
||||
TAG_LENGTH,
|
||||
VIEW_KEY_LENGTH,
|
||||
ADDRESS_REGEX,
|
||||
ACCOUNT_KEY_REGEX,
|
||||
encodeVarint,
|
||||
decodeVarint,
|
||||
ADDRESS_PREFIX_LENGTH,
|
||||
INTEGRATED_PREFIX_LENGTH,
|
||||
} from './constants';
|
||||
import { DecodedAddress, SplitedIntegratedAddress } from './types';
|
||||
import { base58Encode, base58Decode } from '../core/base58';
|
||||
|
|
@ -52,16 +52,14 @@ function createIntegratedAddress(address: string, paymentId: string): string {
|
|||
|
||||
function formatIntegratedAddress(addressDecoded: DecodedAddress, paymentIdBuffer: Buffer): string {
|
||||
const {
|
||||
tag,
|
||||
flag,
|
||||
viewPublicKey,
|
||||
spendPublicKey,
|
||||
viewPublicKey,
|
||||
}: DecodedAddress = addressDecoded;
|
||||
|
||||
const integratedAddressBuffer: Buffer = Buffer.concat([
|
||||
Buffer.from([tag, flag]),
|
||||
viewPublicKey,
|
||||
encodeVarint(INTEGRATED_ADDRESS_PREFIX),
|
||||
spendPublicKey,
|
||||
viewPublicKey,
|
||||
paymentIdBuffer,
|
||||
]);
|
||||
|
||||
|
|
@ -76,31 +74,27 @@ function decodeAddress(address: string): DecodedAddress {
|
|||
throw new Error('Invalid decode address');
|
||||
}
|
||||
|
||||
let offset = TAG_LENGTH + FLAG_LENGTH;
|
||||
const viewPublicKey: Buffer = decodedAddress.subarray(offset, offset + VIEW_KEY_LENGTH);
|
||||
offset += VIEW_KEY_LENGTH;
|
||||
const { value: prefix, length: prefixLength } = decodeVarint(decodedAddress);
|
||||
let offset = prefixLength;
|
||||
const spendPublicKey: Buffer = decodedAddress.subarray(offset, offset + SPEND_KEY_LENGTH);
|
||||
offset += SPEND_KEY_LENGTH;
|
||||
const viewPublicKey: Buffer = decodedAddress.subarray(offset, offset + VIEW_KEY_LENGTH);
|
||||
|
||||
return {
|
||||
tag: INTEGRATED_ADDRESS_TAG_PREFIX,
|
||||
flag: INTEGRATED_ADDRESS_FLAG_PREFIX,
|
||||
viewPublicKey,
|
||||
prefix,
|
||||
spendPublicKey,
|
||||
viewPublicKey,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error(`Error decode address: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function encodeAddress(tag: number, flag: number, spendPublicKey: string, viewPublicKey: string): string {
|
||||
function encodeAddress(prefix: number, spendPublicKey: string, viewPublicKey: string): string {
|
||||
try {
|
||||
if (tag < 0) {
|
||||
throw new Error('Invalid tag');
|
||||
if (prefix < 0) {
|
||||
throw new Error('Invalid prefix');
|
||||
}
|
||||
if (flag < 0) {
|
||||
throw new Error('Invalid flag');
|
||||
}
|
||||
let buf: Buffer = Buffer.from([tag, flag]);
|
||||
|
||||
if (spendPublicKey.length !== 64 && !ACCOUNT_KEY_REGEX.test(spendPublicKey)) {
|
||||
throw new Error('Invalid spendPublicKey: must be a hexadecimal string with a length of 64');
|
||||
|
|
@ -112,7 +106,7 @@ function encodeAddress(tag: number, flag: number, spendPublicKey: string, viewPu
|
|||
}
|
||||
const viewKey: Buffer = Buffer.from(viewPublicKey, 'hex');
|
||||
|
||||
buf = Buffer.concat([buf, spendKey, viewKey]);
|
||||
let buf: Buffer = Buffer.concat([encodeVarint(prefix), spendKey, viewKey]);
|
||||
const hash: string = getChecksum(buf);
|
||||
|
||||
return base58Encode(Buffer.concat([buf, Buffer.from(hash, 'hex')]));
|
||||
|
|
@ -123,9 +117,6 @@ function encodeAddress(tag: number, flag: number, spendPublicKey: string, viewPu
|
|||
|
||||
function getMasterAddress(spendPublicKey: string, viewPublicKey: string): string {
|
||||
try {
|
||||
const tag: number = ADDRESS_TAG_PREFIX;
|
||||
const flag: number = ADDRESS_FLAG_PREFIX;
|
||||
|
||||
if (spendPublicKey.length !== 64 && !ACCOUNT_KEY_REGEX.test(spendPublicKey)) {
|
||||
throw new Error('Invalid spendPublicKey: must be a hexadecimal string with a length of 64');
|
||||
}
|
||||
|
|
@ -134,12 +125,10 @@ function getMasterAddress(spendPublicKey: string, viewPublicKey: string): string
|
|||
throw new Error('Invalid viewPrivateKey: must be a hexadecimal string with a length of 64');
|
||||
}
|
||||
|
||||
const viewPublicKeyBuf: Buffer = Buffer.from(viewPublicKey, 'hex');
|
||||
const spendPublicKeyBuf: Buffer = Buffer.from(spendPublicKey, 'hex');
|
||||
const viewPublicKeyBuf: Buffer = Buffer.from(viewPublicKey, 'hex');
|
||||
|
||||
let buf: Buffer = Buffer.from([tag, flag]);
|
||||
|
||||
buf = Buffer.concat([buf, spendPublicKeyBuf, viewPublicKeyBuf]);
|
||||
let buf: Buffer = Buffer.concat([encodeVarint(ADDRESS_PREFIX), spendPublicKeyBuf, viewPublicKeyBuf]);
|
||||
const hash: string = getChecksum(buf);
|
||||
|
||||
return base58Encode(Buffer.concat([buf, Buffer.from(hash, 'hex')]));
|
||||
|
|
@ -163,7 +152,8 @@ function splitIntegratedAddress(integratedAddress: string): SplitedIntegratedAdd
|
|||
throw new Error('spendPublicKey or viewPublicKey are missing');
|
||||
}
|
||||
|
||||
const paymentId: string = base58Decode(integratedAddress).subarray(66, 66 + PAYMENT_ID_LENGTH).toString('hex');
|
||||
const paymentIdOffset: number = INTEGRATED_PREFIX_LENGTH + SPEND_KEY_LENGTH + VIEW_KEY_LENGTH;
|
||||
const paymentId: string = base58Decode(integratedAddress).subarray(paymentIdOffset, paymentIdOffset + PAYMENT_ID_LENGTH).toString('hex');
|
||||
const masterAddress: string = getMasterAddress(spendPublicKey, viewPublicKey);
|
||||
|
||||
return {
|
||||
|
|
@ -178,14 +168,14 @@ function splitIntegratedAddress(integratedAddress: string): SplitedIntegratedAdd
|
|||
|
||||
|
||||
/*
|
||||
* Retrieves public spend and view keys from the Zano address.
|
||||
* Retrieves public spend and view keys from the Lethean address.
|
||||
*
|
||||
* This function decodes a Zano address and Integrated address from its Base58 representation and extracts
|
||||
* This function decodes a Lethean address and Integrated address from its Base58 representation and extracts
|
||||
* the spend and view keys contained within it. If the address is not in a valid
|
||||
* Base58 format, or if the resulting buffer does not conform to expected length specifics,
|
||||
* an error is thrown.
|
||||
*
|
||||
* @param {string} address - A Zano address and Integrated address in Base58 format.
|
||||
* @param {string} address - A Lethean address and Integrated address in Base58 format.
|
||||
* @returns { ZarcanumAddressKeys } An object containing the spend and view keys.
|
||||
* @throws { Error } Throws an error if the address format or buffer length is invalid.
|
||||
*/
|
||||
|
|
@ -207,15 +197,17 @@ function getKeysFromAddress(address: string): ZarcanumAddressKeys {
|
|||
throw new Error('Invalid address checksum');
|
||||
}
|
||||
|
||||
const { length: prefixLength } = decodeVarint(buf);
|
||||
|
||||
const spendPublicKey: string = Buffer.from(
|
||||
buf.buffer,
|
||||
TAG_LENGTH + FLAG_LENGTH,
|
||||
prefixLength,
|
||||
SPEND_KEY_LENGTH,
|
||||
).toString('hex');
|
||||
|
||||
const viewPublicKey: string = Buffer.from(
|
||||
buf.buffer,
|
||||
TAG_LENGTH + FLAG_LENGTH + SPEND_KEY_LENGTH,
|
||||
prefixLength + SPEND_KEY_LENGTH,
|
||||
VIEW_KEY_LENGTH,
|
||||
).toString('hex');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,55 @@
|
|||
export const TAG_LENGTH = 1;
|
||||
export const FLAG_LENGTH = 1;
|
||||
export const SPEND_KEY_LENGTH = 32;
|
||||
export const VIEW_KEY_LENGTH = 32;
|
||||
export const CHECKSUM_LENGTH = 4;
|
||||
|
||||
// Lethean address prefix as a varint integer.
|
||||
// Standard addresses start with 'iTHN', integrated with 'iTHn'.
|
||||
// See blockchain/src/config/currency_config.h for canonical values.
|
||||
export const ADDRESS_PREFIX = 0x1eaf7;
|
||||
export const INTEGRATED_ADDRESS_PREFIX = 0xdeaf7;
|
||||
|
||||
// Varint-encode a prefix integer into a Buffer.
|
||||
export function encodeVarint(value: number): Buffer {
|
||||
const bytes: number[] = [];
|
||||
while (value >= 0x80) {
|
||||
bytes.push((value & 0x7f) | 0x80);
|
||||
value >>>= 7;
|
||||
}
|
||||
bytes.push(value);
|
||||
return Buffer.from(bytes);
|
||||
}
|
||||
|
||||
// Decode a varint from the start of a buffer, returning the value and byte length consumed.
|
||||
export function decodeVarint(buf: Buffer): { value: number; length: number } {
|
||||
let value = 0;
|
||||
let shift = 0;
|
||||
let length = 0;
|
||||
let byte: number;
|
||||
do {
|
||||
byte = buf[length];
|
||||
value |= (byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
length++;
|
||||
} while ((byte & 0x80) !== 0);
|
||||
return { value, length };
|
||||
}
|
||||
|
||||
export const ADDRESS_PREFIX_LENGTH: number = encodeVarint(ADDRESS_PREFIX).length;
|
||||
export const INTEGRATED_PREFIX_LENGTH: number = encodeVarint(INTEGRATED_ADDRESS_PREFIX).length;
|
||||
|
||||
export const BUFFER_ADDRESS_LENGTH: number =
|
||||
TAG_LENGTH +
|
||||
FLAG_LENGTH +
|
||||
ADDRESS_PREFIX_LENGTH +
|
||||
SPEND_KEY_LENGTH +
|
||||
VIEW_KEY_LENGTH +
|
||||
CHECKSUM_LENGTH;
|
||||
export const ADDRESS_REGEX = /^Z[a-zA-Z0-9]{96}$/;
|
||||
export const INTEGRATED_ADDRESS_REGEX = /^iZ[a-zA-Z0-9]{106}$/;
|
||||
export const ADDRESS_REGEX = /^iTHN[a-zA-Z0-9]{94}$/;
|
||||
export const INTEGRATED_ADDRESS_REGEX = /^iTHn[a-zA-Z0-9]{105}$/;
|
||||
export const PAYMENT_ID_LENGTH = 8;
|
||||
export const INTEGRATED_ADDRESS_FLAG_PREFIX = 0x6c;
|
||||
export const INTEGRATED_ADDRESS_TAG_PREFIX = 0xf8;
|
||||
export const ADDRESS_FLAG_PREFIX = 0x01;
|
||||
export const ADDRESS_TAG_PREFIX = 0xC5;
|
||||
export const BUFFER_INTEGRATED_ADDRESS_LENGTH =
|
||||
BUFFER_ADDRESS_LENGTH +
|
||||
PAYMENT_ID_LENGTH;
|
||||
export const BUFFER_INTEGRATED_ADDRESS_LENGTH: number =
|
||||
INTEGRATED_PREFIX_LENGTH +
|
||||
SPEND_KEY_LENGTH +
|
||||
VIEW_KEY_LENGTH +
|
||||
PAYMENT_ID_LENGTH +
|
||||
CHECKSUM_LENGTH;
|
||||
export const PAYMENT_ID_REGEX = /^[a-fA-F0-9]{16}$/;
|
||||
export const ACCOUNT_KEY_REGEX = /^([0-9a-fA-F]{2})+$/;
|
||||
|
|
@ -4,10 +4,9 @@ export type ZarcanumAddressKeys = {
|
|||
}
|
||||
|
||||
export type DecodedAddress = {
|
||||
tag: number;
|
||||
flag: number;
|
||||
viewPublicKey: Buffer;
|
||||
prefix: number;
|
||||
spendPublicKey: Buffer;
|
||||
viewPublicKey: Buffer;
|
||||
}
|
||||
|
||||
export type SplitedIntegratedAddress = {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export class BinaryArchive {
|
|||
|
||||
/**
|
||||
*
|
||||
* @see https://github.com/hyle-team/zano/blob/69a5d42d9908b7168247e103b2b40aae8c1fb3f5/src/common/varint.h#L59
|
||||
* @see Upstream ref: hyle-team/zano@69a5d42 src/common/varint.h#L59
|
||||
*/
|
||||
readVarint(): bigint {
|
||||
let varint = 0n;
|
||||
|
|
|
|||
|
|
@ -9,22 +9,22 @@ const { red } = ec.curve;
|
|||
export const A = new BN(486662, 10).toRed(red);
|
||||
|
||||
// sqrt(-1)
|
||||
// https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-ops-data.c#L12
|
||||
// Upstream ref: hyle-team/zano@2817090 src/crypto/crypto-ops-data.c#L12
|
||||
//export const sqrtm1 = new BN(1).toRed(red).redNeg().redSqrt();
|
||||
export const sqrtm1: RedBN = new BN('547cdb7fb03e20f4d4b2ff66c2042858d0bce7f952d01b873b11e4d8b5f15f3d', 'hex').toRed(red);
|
||||
|
||||
// sqrt(-2 * A * (A + 2))
|
||||
// https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-ops-data.c#L843
|
||||
// Upstream ref: hyle-team/zano@2817090 src/crypto/crypto-ops-data.c#L843
|
||||
export const fffb1: RedBN = new BN('7e71fbefdad61b1720a9c53741fb19e3d19404a8b92a738d22a76975321c41ee', 'hex').toRed(red);
|
||||
|
||||
// sqrt(2 * A * (A + 2))
|
||||
// https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-ops-data.c#L844
|
||||
// Upstream ref: hyle-team/zano@2817090 src/crypto/crypto-ops-data.c#L844
|
||||
export const fffb2: RedBN = new BN('32f9e1f5fba5d3096e2bae483fe9a041ae21fcb9fba908202d219b7c9f83650d', 'hex').toRed(red);
|
||||
|
||||
// sqrt(-sqrt(-1) * A * (A + 2))
|
||||
// https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-ops-data.c#L845
|
||||
// Upstream ref: hyle-team/zano@2817090 src/crypto/crypto-ops-data.c#L845
|
||||
export const fffb3: RedBN = new BN('1a43f3031067dbf926c0f4887ef7432eee46fc08a13f4a49853d1903b6b39186', 'hex').toRed(red);
|
||||
|
||||
// sqrt(sqrt(-1) * A * (A + 2))
|
||||
// https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-ops-data.c#L846
|
||||
// Upstream ref: hyle-team/zano@2817090 src/crypto/crypto-ops-data.c#L846
|
||||
export const fffb4: RedBN = new BN('674a110d14c208efb89546403f0da2ed4024ff4ea5964229581b7d8717302c66', 'hex').toRed(red);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export function getDerivationToScalar(txPubKey: string, secViewKey: string, outI
|
|||
|
||||
/*
|
||||
* out.concealing_point = (crypto::hash_helper_t::hs(CRYPTO_HDS_OUT_CONCEALING_POINT, h) * crypto::point_t(apa.view_public_key)).to_public_key(); // Q = 1/8 * Hs(domain_sep, Hs(8 * r * V, i) ) * 8 * V
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/currency_core/currency_format_utils.cpp#L1270
|
||||
* Upstream ref: hyle-team/zano@2817090src/currency_core/currency_format_utils.cpp#L1270
|
||||
*/
|
||||
export function calculateConcealingPoint(Hs: Buffer, pubViewKeyBuff: Buffer): Buffer {
|
||||
const scalar: BN = decodeScalar(Hs, 'Invalid sсalar');
|
||||
|
|
@ -68,7 +68,7 @@ export function calculateConcealingPoint(Hs: Buffer, pubViewKeyBuff: Buffer): Bu
|
|||
|
||||
/*
|
||||
* out.blinded_asset_id = (crypto::c_scalar_1div8 * blinded_asset_id).to_public_key(); // T = 1/8 * (H_asset + s * X)
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/currency_core/currency_format_utils.cpp#L1278
|
||||
* Upstream ref: hyle-team/zano@2817090src/currency_core/currency_format_utils.cpp#L1278
|
||||
*/
|
||||
export function calculateBlindedAssetId(Hs: Buffer, assetId: Buffer, X: Buffer): Buffer {
|
||||
const assetIdCopy: Buffer = Buffer.from(assetId);
|
||||
|
|
@ -88,11 +88,11 @@ export function calculateBlindedAssetId(Hs: Buffer, assetId: Buffer, X: Buffer):
|
|||
}
|
||||
|
||||
// todo: crypto::point_t asset_id = blinded_asset_id - asset_id_blinding_mask * crypto::c_point_X; // H = T - s * X
|
||||
// https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/currency_core/currency_format_utils.cpp#L3289
|
||||
// Upstream ref: hyle-team/zano@2817090src/currency_core/currency_format_utils.cpp#L3289
|
||||
|
||||
/*
|
||||
* generate_key_derivation
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L175
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L175
|
||||
*/
|
||||
export function generateKeyDerivation(txPubKey: Buffer, secKeyView: Buffer): Buffer {
|
||||
const s: BN = decodeScalar(secKeyView, 'Invalid secret key');
|
||||
|
|
@ -105,7 +105,7 @@ export function generateKeyDerivation(txPubKey: Buffer, secKeyView: Buffer): Buf
|
|||
|
||||
/*
|
||||
* derive_public_key
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L207
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L207
|
||||
*/
|
||||
export function derivePublicKey(
|
||||
derivation: Buffer,
|
||||
|
|
@ -126,7 +126,7 @@ export function derivePublicKey(
|
|||
|
||||
/*
|
||||
* derive_secret_key
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L227
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L227
|
||||
*/
|
||||
export function deriveSecretKey(derivation: Buffer, outIndex: number, sec: Buffer): Buffer {
|
||||
const s: BN = decodeScalar(sec, 'Invalid secret key');
|
||||
|
|
@ -139,7 +139,7 @@ export function deriveSecretKey(derivation: Buffer, outIndex: number, sec: Buffe
|
|||
|
||||
/*
|
||||
* derivation_to_scalar
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L190
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L190
|
||||
*/
|
||||
export function derivationToScalar(derivation: Buffer, outIndex: number): Buffer {
|
||||
const data: Buffer = Buffer.concat([
|
||||
|
|
@ -155,7 +155,7 @@ export function fastHash(data: Buffer): Buffer {
|
|||
}
|
||||
|
||||
/*
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-sugar.h#L1386
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto-sugar.h#L1386
|
||||
*/
|
||||
export function hs(str32: Buffer, h: Buffer): Buffer {
|
||||
const elements: Buffer[] = [str32, h];
|
||||
|
|
@ -165,7 +165,7 @@ export function hs(str32: Buffer, h: Buffer): Buffer {
|
|||
|
||||
/*
|
||||
* hash_to_scalar
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L115
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L115
|
||||
*/
|
||||
export function hashToScalar(data: Buffer): Buffer {
|
||||
const hash: Buffer = fastHash(data);
|
||||
|
|
@ -179,7 +179,7 @@ export function reduceScalar32(scalar: Buffer): Buffer {
|
|||
|
||||
/*
|
||||
* generate_key_image
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L296
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L296
|
||||
*/
|
||||
export function calculateKeyImage(pub: Buffer, sec: Buffer): Buffer {
|
||||
const s: BN = decodeScalar(sec, 'Invalid secret key');
|
||||
|
|
@ -190,7 +190,7 @@ export function calculateKeyImage(pub: Buffer, sec: Buffer): Buffer {
|
|||
|
||||
/*
|
||||
* hash_to_ec
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L286
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L286
|
||||
*/
|
||||
export function hashToEc(ephemeralPubKey: Buffer): curve.base.BasePoint {
|
||||
const hash: Buffer = fastHash(ephemeralPubKey);
|
||||
|
|
@ -200,7 +200,7 @@ export function hashToEc(ephemeralPubKey: Buffer): curve.base.BasePoint {
|
|||
|
||||
/*
|
||||
* ge_fromfe_frombytes_vartime
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto-ops.c#L2209
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto-ops.c#L2209
|
||||
*/
|
||||
export function hashToPoint(hash: Buffer): curve.edwards.EdwardsPoint {
|
||||
const u: RedBN = decodeInt(hash).toRed(ec.curve.red);
|
||||
|
|
@ -292,7 +292,7 @@ export function chachaCrypt(paymentId: Buffer, derivation: Buffer): Buffer {
|
|||
|
||||
/*
|
||||
* keys_from_default
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L88
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L88
|
||||
*/
|
||||
export function keysFromDefault(aPart: Buffer, keysSeedBinarySize: number): SpendKeypair {
|
||||
// aPart == 32 bytes
|
||||
|
|
@ -330,7 +330,7 @@ export function keysFromDefault(aPart: Buffer, keysSeedBinarySize: number): Spen
|
|||
|
||||
/*
|
||||
* generate_seed_keys
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L108
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L108
|
||||
*/
|
||||
export function generateSeedKeys(keysSeedBinarySize: number): SpendKeypair {
|
||||
const keysSeedBinary: Buffer = getRandomBytes(keysSeedBinarySize);
|
||||
|
|
@ -370,7 +370,7 @@ export function getRandomBytes(numBytes: number): Buffer {
|
|||
|
||||
/*
|
||||
* dependent_key
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L129
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L129
|
||||
*/
|
||||
export function dependentKey(secretSpendKey: Buffer): string {
|
||||
if (secretSpendKey.length !== 32) {
|
||||
|
|
@ -382,7 +382,7 @@ export function dependentKey(secretSpendKey: Buffer): string {
|
|||
|
||||
/*
|
||||
* secret_key_to_public_key
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L165
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L165
|
||||
*/
|
||||
export function secretKeyToPublicKey(secretViewKey: Buffer): string {
|
||||
const s: BN = decodeScalar(secretViewKey, 'Invalid secret key');
|
||||
|
|
@ -393,7 +393,7 @@ export function secretKeyToPublicKey(secretViewKey: Buffer): string {
|
|||
|
||||
/*
|
||||
* generate_signature
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L241
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L241
|
||||
*/
|
||||
export function generateSignature(message: Buffer, privateKey: Buffer, pubKey: Buffer): string {
|
||||
const h: Buffer = fastHash(message);
|
||||
|
|
@ -441,7 +441,7 @@ export function generateSignature(message: Buffer, privateKey: Buffer, pubKey: B
|
|||
|
||||
/*
|
||||
* check_signature
|
||||
* https://github.com/hyle-team/zano/blob/2817090c8ac7639d6f697d00fc8bcba2b3681d90/src/crypto/crypto.cpp#L265
|
||||
* Upstream ref: hyle-team/zano@2817090src/crypto/crypto.cpp#L265
|
||||
*/
|
||||
export function checkSignature(
|
||||
message: Buffer,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,55 @@
|
|||
export const TAG_LENGTH = 1;
|
||||
export const FLAG_LENGTH = 1;
|
||||
export const SPEND_KEY_LENGTH = 32;
|
||||
export const VIEW_KEY_LENGTH = 32;
|
||||
export const CHECKSUM_LENGTH = 4;
|
||||
|
||||
// Lethean address prefix as a varint integer.
|
||||
// Standard addresses start with 'iTHN', integrated with 'iTHn'.
|
||||
export const ADDRESS_PREFIX = 0x1eaf7;
|
||||
export const INTEGRATED_ADDRESS_PREFIX = 0xdeaf7;
|
||||
|
||||
// Varint-encode a prefix integer into a Buffer.
|
||||
export function encodeVarint(value: number): Buffer {
|
||||
const bytes: number[] = [];
|
||||
while (value >= 0x80) {
|
||||
bytes.push((value & 0x7f) | 0x80);
|
||||
value >>>= 7;
|
||||
}
|
||||
bytes.push(value);
|
||||
return Buffer.from(bytes);
|
||||
}
|
||||
|
||||
// Decode a varint from the start of a buffer, returning the value and byte length consumed.
|
||||
export function decodeVarint(buf: Buffer): { value: number; length: number } {
|
||||
let value = 0;
|
||||
let shift = 0;
|
||||
let length = 0;
|
||||
let byte: number;
|
||||
do {
|
||||
byte = buf[length];
|
||||
value |= (byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
length++;
|
||||
} while ((byte & 0x80) !== 0);
|
||||
return { value, length };
|
||||
}
|
||||
|
||||
export const ADDRESS_PREFIX_LENGTH: number = encodeVarint(ADDRESS_PREFIX).length;
|
||||
export const INTEGRATED_PREFIX_LENGTH: number = encodeVarint(INTEGRATED_ADDRESS_PREFIX).length;
|
||||
|
||||
export const BUFFER_ADDRESS_LENGTH: number =
|
||||
TAG_LENGTH +
|
||||
FLAG_LENGTH +
|
||||
ADDRESS_PREFIX_LENGTH +
|
||||
SPEND_KEY_LENGTH +
|
||||
VIEW_KEY_LENGTH +
|
||||
CHECKSUM_LENGTH;
|
||||
export const ADDRESS_REGEX = /^Z[a-zA-Z0-9]{96}$/;
|
||||
export const INTEGRATED_ADDRESS_REGEX = /^iZ[a-zA-Z0-9]{106}$/;
|
||||
export const ADDRESS_REGEX = /^iTHN[a-zA-Z0-9]{94}$/;
|
||||
export const INTEGRATED_ADDRESS_REGEX = /^iTHn[a-zA-Z0-9]{105}$/;
|
||||
export const PAYMENT_ID_LENGTH = 8;
|
||||
export const INTEGRATED_ADDRESS_FLAG_PREFIX = 0x6c;
|
||||
export const INTEGRATED_ADDRESS_TAG_PREFIX = 0xf8;
|
||||
export const ADDRESS_FLAG_PREFIX = 0x01;
|
||||
export const ADDRESS_TAG_PREFIX = 0xC5;
|
||||
export const BUFFER_INTEGRATED_ADDRESS_LENGTH =
|
||||
BUFFER_ADDRESS_LENGTH +
|
||||
PAYMENT_ID_LENGTH;
|
||||
export const BUFFER_INTEGRATED_ADDRESS_LENGTH: number =
|
||||
INTEGRATED_PREFIX_LENGTH +
|
||||
SPEND_KEY_LENGTH +
|
||||
VIEW_KEY_LENGTH +
|
||||
PAYMENT_ID_LENGTH +
|
||||
CHECKSUM_LENGTH;
|
||||
export const PAYMENT_ID_REGEX = /^[a-fA-F0-9]{16}$/;
|
||||
export const PUBLIC_KEY_REGEX = /^[0-9a-f]{64}$/i;
|
||||
export const HEX_PUBKEY_REGEX = /^[a-fA-F0-9]{64}$/;
|
||||
|
|
|
|||
|
|
@ -3,19 +3,18 @@ import {
|
|||
BUFFER_ADDRESS_LENGTH,
|
||||
BUFFER_INTEGRATED_ADDRESS_LENGTH,
|
||||
CHECKSUM_LENGTH,
|
||||
FLAG_LENGTH,
|
||||
INTEGRATED_ADDRESS_REGEX,
|
||||
PUBLIC_KEY_REGEX,
|
||||
SPEND_KEY_LENGTH,
|
||||
TAG_LENGTH,
|
||||
VIEW_KEY_LENGTH,
|
||||
decodeVarint,
|
||||
} from './constants';
|
||||
import {
|
||||
DecodeVoutResult,
|
||||
DecodeTransactionResult,
|
||||
ZarcanumAddressKeys,
|
||||
} from './types';
|
||||
import { isTransactionObjectV3, satoshiToZano } from './utils/functions';
|
||||
import { isTransactionObjectV3, satoshiToLethean } from './utils/functions';
|
||||
import { base58Decode } from '../core/base58';
|
||||
import { getChecksum, secretKeyToPublicKey } from '../core/crypto';
|
||||
import {
|
||||
|
|
@ -109,7 +108,7 @@ export function decodeTransaction(
|
|||
|
||||
return {
|
||||
ok: true,
|
||||
amount: satoshiToZano(totalAmount.toString()),
|
||||
amount: satoshiToLethean(totalAmount.toString()),
|
||||
...(paymentId ? { paymentId } : { }),
|
||||
};
|
||||
}
|
||||
|
|
@ -187,15 +186,17 @@ function getKeysFromAddress(address: string): ZarcanumAddressKeys {
|
|||
throw new Error('Invalid address checksum');
|
||||
}
|
||||
|
||||
const { length: prefixLength } = decodeVarint(buf);
|
||||
|
||||
const spendPublicKey: string = Buffer.from(
|
||||
buf.buffer,
|
||||
TAG_LENGTH + FLAG_LENGTH,
|
||||
prefixLength,
|
||||
SPEND_KEY_LENGTH,
|
||||
).toString('hex');
|
||||
|
||||
const viewPublicKey: string = Buffer.from(
|
||||
buf.buffer,
|
||||
TAG_LENGTH + FLAG_LENGTH + SPEND_KEY_LENGTH,
|
||||
prefixLength + SPEND_KEY_LENGTH,
|
||||
VIEW_KEY_LENGTH,
|
||||
).toString('hex');
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export function timestampMsToDate(timestampMs: number): Date {
|
|||
return new Date(timestampMs * 1000);
|
||||
}
|
||||
|
||||
export function satoshiToZano(satoshiAmount: string): string {
|
||||
export function satoshiToLethean(satoshiAmount: string): string {
|
||||
const satoshi: Big = new Big(satoshiAmount);
|
||||
if (satoshi.lt(0)) {
|
||||
throw new Error('The number of satoshi cannot be negative');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
export const CRYPTO_HDS_OUT_AMOUNT_MASK = Buffer.from('ZANO_HDS_OUT_AMOUNT_MASK_______\0', 'ascii');
|
||||
export const CRYPTO_HDS_OUT_CONCEALING_POINT = Buffer.from('ZANO_HDS_OUT_CONCEALING_POINT__\0', 'ascii');
|
||||
export const CRYPTO_HDS_OUT_ASSET_BLIND_MASK = Buffer.from('ZANO_HDS_OUT_ASSET_BLIND_MASK__\0', 'ascii');
|
||||
// Note: The ZANO_HDS_* string values above are protocol-level constants shared with the Lethean
|
||||
// blockchain daemon. They must not be changed or transaction decoding will break.
|
||||
export const POINT_X: Buffer = Buffer.from('3a25bcdb43f5d2c9dd063dc39a9e0987bafc6fcf2df1bc76322d75884a4a3820', 'hex');
|
||||
export const NATIVE_ASSET_ID: Buffer = Buffer.from(
|
||||
'd6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a',
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ describe('generate account', () => {
|
|||
});
|
||||
|
||||
expect(generateAccount()).toMatchObject({
|
||||
address: 'ZxBpGz8qdG3SxgBYFKJqxjThPZpjqW1ouK3ZsyZnZCUqQ4Ndc9PiqkdJuEicMXPPSW5JidxK5bye7UYc1hkTHhxc1w4temC2A',
|
||||
address: 'iTHNJKCusvaD9NZX9bjzTnVCrp92549Gf7m926mybX5KVXSMHP5Ejk486WUfM5FtiTgzaLmyGXcvrdEiFWyPKihW3BDTVzaifp',
|
||||
secretSpendKey: '6c225665aadb81ebce41bd94cbc78250aaf62f2636819b1cdcf47d4cbcd2b00d',
|
||||
publicSpendKey: '0c27ece0fb489b344915d12745a89f9b6cb307c384286be12ae9311942aa89db',
|
||||
});
|
||||
|
|
@ -32,7 +32,7 @@ describe('generate account', () => {
|
|||
});
|
||||
|
||||
describe('address validation', () => {
|
||||
const address = 'ZxDFpn4k7xVYyc9VZ3LphrJbkpc46xfREace5bme1aXiMzKPAHA8jsTWcHSXhv9AdodSaoGXK9Mg7bk3ec4FkQrj357fZPWZX';
|
||||
const address = 'iTHNdF5eT7c9VJpNtt3geei3o4mye12eFe6bNZAzxtiBg49XYns3HAkBVBn3N46s9A8Ai7PBbZxnbQZ3huf2zg3N3AA2NQ5bHR';
|
||||
const secretSpendKey = '80b3e96a3eb765332b0fd3e44e0fefa58747a70025bf91aa4a7b758ab6f5590d';
|
||||
const publicSpendKey = 'b3eee2376f32bf2bfb5cf9c023f569380c84ac8c64ddc8f7c109730dc8e97d7a';
|
||||
const secretViewKey = '3e75ffee51eb21b1d6404ddcab5b3aaa49edbfe225e9a893d87074aacae46b09';
|
||||
|
|
|
|||
|
|
@ -1,54 +1,48 @@
|
|||
import { splitIntegratedAddress, getIntegratedAddress, getKeysFromAddress, encodeAddress } from '../src/address/address-utils';
|
||||
import { ADDRESS_PREFIX } from '../src/address/constants';
|
||||
import { base58Decode } from '../src/core/base58';
|
||||
|
||||
describe(
|
||||
'testing the correctness of the address encoding function encodeAddress',
|
||||
() => {
|
||||
const tag = 197;
|
||||
const flag = 1;
|
||||
const prefix = ADDRESS_PREFIX;
|
||||
const spendPublicKey = '9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa';
|
||||
const viewPublicKey = 'a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3';
|
||||
const address = encodeAddress(tag, flag, spendPublicKey, viewPublicKey);
|
||||
const address = encodeAddress(prefix, spendPublicKey, viewPublicKey);
|
||||
|
||||
it('checking the correctness of the result', () => {
|
||||
expect(address)
|
||||
.toBe('ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH');
|
||||
.toBe('iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi');
|
||||
});
|
||||
|
||||
it('checking the correctness of the address length', () => {
|
||||
expect(address).toHaveLength(97);
|
||||
expect(address).toHaveLength(98);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid tag', () => {
|
||||
it('should throw an error for invalid prefix', () => {
|
||||
expect(() => {
|
||||
encodeAddress(-197, 1, '...', '...');
|
||||
}).toThrow('Invalid tag');
|
||||
});
|
||||
|
||||
it('should throw an error for invalid flag', () => {
|
||||
expect(() => {
|
||||
encodeAddress(197, -1, '...', '...');
|
||||
}).toThrow('Invalid flag');
|
||||
encodeAddress(-1, '...', '...');
|
||||
}).toThrow('Invalid prefix');
|
||||
});
|
||||
|
||||
it('should throw an error for invalid public key', () => {
|
||||
expect(() => {
|
||||
encodeAddress(197, 1, 'invalid', viewPublicKey);
|
||||
encodeAddress(prefix, 'invalid', viewPublicKey);
|
||||
}).toThrow('Invalid spendPublicKey: must be a hexadecimal string with a length of 64');
|
||||
});
|
||||
|
||||
it('should throw an error for invalid private key', () => {
|
||||
expect(() => {
|
||||
encodeAddress(197, 1, spendPublicKey, 'invalid');
|
||||
encodeAddress(prefix, spendPublicKey, 'invalid');
|
||||
}).toThrow('Invalid viewPrivateKey: must be a hexadecimal string with a length of 64');
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe(
|
||||
'testing the correctness of the address decoding function getKeysFromZanoAddress',
|
||||
'testing the correctness of the address decoding function getKeysFromLetheanAddress',
|
||||
() => {
|
||||
const address = 'ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH';
|
||||
const address = 'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi';
|
||||
const spendPublicKey = '9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa';
|
||||
const viewPublicKey = 'a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3';
|
||||
|
||||
|
|
@ -66,14 +60,14 @@ describe(
|
|||
});
|
||||
|
||||
it('should throw an invalid character in base58 string', () => {
|
||||
const invalidAddress = 'ZxD5aoLDPTdcaRx4uOpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH';
|
||||
const invalidAddress = 'iTHNavWQHS59AinRwcPqSqBKjckre7PgOZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi';
|
||||
expect(() => {
|
||||
getKeysFromAddress(invalidAddress);
|
||||
}).toThrow('base58 string block contains invalid character');
|
||||
});
|
||||
|
||||
it('should throw an invalid base58 string size', () => {
|
||||
const invalidAddress = 'Z';
|
||||
const invalidAddress = 'iTHN';
|
||||
expect(() => {
|
||||
base58Decode(invalidAddress);
|
||||
}).toThrow('base58 string has an invalid size');
|
||||
|
|
@ -81,51 +75,50 @@ describe(
|
|||
|
||||
it('should throw an invalid address checksum', () => {
|
||||
expect(() => {
|
||||
(getKeysFromAddress('Zx' + '1'.repeat(95)));
|
||||
(getKeysFromAddress('iTHN' + '1'.repeat(94)));
|
||||
}).toThrow('Invalid address checksum');
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe('getIntegratedAddress', () => {
|
||||
const SUFFIX_LENGTH = 18; // paymentId + checksum
|
||||
// The last SUFFIX_LENGTH characters of an integrated address encode the paymentId + checksum,
|
||||
// which differ each time a random paymentId is generated. The deterministic prefix is stable.
|
||||
const SUFFIX_LENGTH = 17;
|
||||
|
||||
// Define test data
|
||||
const integratedAddress = 'iZ2kFmwxRHoaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e47JPoHxGL5UU2D1tpQMg4';
|
||||
const masterAddress = 'ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH';
|
||||
const masterAddress2 = 'ZxDG8UrQMEVaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e41KkqnWH8F';
|
||||
// Define test data - Lethean iTHN/iTHn addresses
|
||||
const integratedAddress = 'iTHnVGr7tms9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJQSA6PNs1faBfevEK7';
|
||||
const masterAddress = 'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi';
|
||||
const masterAddress2 = 'iTHNV7oXHXXUtKxTWVi267XoQMNrbVzFk2tz6tmus8doM5KuSrewKQ2bMbwmzcBEhJGuGNwfPMnuxc6Rx5ZvvXro86z84X5t3V';
|
||||
|
||||
const masterBasedIntegratedAddress = 'iZ2Zi6RmTWwcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTqEsjvJoco1aLSZXS6T';
|
||||
const master2BasedIntegratedAddress = 'iZ2kFmwxRHoaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e47JQQbd6iYGx1S6AdHpq6';
|
||||
|
||||
// Compute desired outcomes for the slice operation
|
||||
// The deterministic prefix of an integrated address derived from each input
|
||||
const integratedAddressWithoutSuffix: string = integratedAddress.slice(0, -SUFFIX_LENGTH);
|
||||
const masterBasedIntegratedAddressWithoutSuffix: string = masterBasedIntegratedAddress.slice(0, -SUFFIX_LENGTH);
|
||||
const master2BasedIntegratedAddressWithoutSuffix: string = master2BasedIntegratedAddress.slice(0, -SUFFIX_LENGTH);
|
||||
const masterBasedPrefix: string = 'iTHnVGr7tms9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJ';
|
||||
const master2BasedPrefix: string = 'iTHnPU9EtsKUtKxTWVi267XoQMNrbVzFk2tz6tmus8doM5KuSrewKQ2bMbwmzcBEhJGuGNwfPMnuxc6Rx5ZvvXroYMR';
|
||||
|
||||
// Addresses returned by ZanoAddressUtils
|
||||
// Addresses returned by getIntegratedAddress (random paymentId each time)
|
||||
const addressFromIntegrated: string = getIntegratedAddress(integratedAddress);
|
||||
const addressFromMaster: string = getIntegratedAddress(masterAddress);
|
||||
const addressFromMaster2: string = getIntegratedAddress(masterAddress2);
|
||||
|
||||
it('ensures that truncating the last 18 characters from the integrated address is correct', () => {
|
||||
it('ensures deterministic prefix from integrated address input is correct', () => {
|
||||
expect(addressFromIntegrated.slice(0, -SUFFIX_LENGTH)).toBe(integratedAddressWithoutSuffix);
|
||||
});
|
||||
|
||||
it('ensures that truncating the last 18 characters from the master-based integrated address is correct', () => {
|
||||
expect(addressFromMaster.slice(0, -SUFFIX_LENGTH)).toBe(masterBasedIntegratedAddressWithoutSuffix);
|
||||
it('ensures deterministic prefix from master address input is correct', () => {
|
||||
expect(addressFromMaster.slice(0, masterBasedPrefix.length)).toBe(masterBasedPrefix);
|
||||
});
|
||||
|
||||
it('ensures that truncating the last 18 characters from the second master-based integrated address is correct', () => {
|
||||
expect(addressFromMaster2.slice(0, -SUFFIX_LENGTH)).toBe(master2BasedIntegratedAddressWithoutSuffix);
|
||||
it('ensures deterministic prefix from second master address input is correct', () => {
|
||||
expect(addressFromMaster2.slice(0, master2BasedPrefix.length)).toBe(master2BasedPrefix);
|
||||
});
|
||||
});
|
||||
|
||||
describe(
|
||||
'testing the correctness of the address decoding in function splitIntegratedAddress',
|
||||
() => {
|
||||
const integratedAddress = 'iZ2kFmwxRHoaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e47JPoHxGL5UU2D1tpQMg4';
|
||||
const masterAddress = 'ZxDG8UrQMEVaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH99BJ6cnbAtJTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e41KkqnWH8F';
|
||||
const integratedAddress = 'iTHnVGr7tms9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJQSA6PNs1faBfevEK7';
|
||||
const masterAddress = 'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi';
|
||||
const paymentId = '1e4cbed444118c99';
|
||||
const invalidintegratedAddress = 'i03McELC3jGTgUnZjPj9CTCTKy1qqM9wPCTp92uBC7e47JR67Qv6wMFaRxm1ni8HnfUTkYuKbni8s4CE2Z4GgFfH999Pvhkaga42D1npn1Vc';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
|
||||
import { encodeAddress, getKeysFromAddress } from '../src/address/address-utils';
|
||||
import { ADDRESS_PREFIX } from '../src/address/constants';
|
||||
import { base58Decode, base58Encode } from '../src/core/base58';
|
||||
import type { ZarcanumAddressKeys } from '../src/address/types';
|
||||
|
||||
const rawAddressBufferHex = 'c5 01 9f 5e 1f a9 36 30 d4 b2 81 b1 8b b6 7a 3d b7 9e 96 22 fc 70 3c c3 ad 4a 45 3a 82 e0 a3 6d 51 fa a3 f2 08 c8 f9 ba 49 ba b2 8e ed 62 b3 5b 0f 6b e0 a2 97 bc d8 5c 2f aa 1e b1 82 05 27 bc f7 e3 e2 38 1c d6';
|
||||
// Lethean varint prefix 0x1eaf7 = [0xf7, 0xd5, 0x07] followed by spend key, view key, checksum
|
||||
const rawAddressBufferHex = 'f7 d5 07 9f 5e 1f a9 36 30 d4 b2 81 b1 8b b6 7a 3d b7 9e 96 22 fc 70 3c c3 ad 4a 45 3a 82 e0 a3 6d 51 fa a3 f2 08 c8 f9 ba 49 ba b2 8e ed 62 b3 5b 0f 6b e0 a2 97 bc d8 5c 2f aa 1e b1 82 05 27 bc f7 e3 ac c8 50 23';
|
||||
|
||||
function dataToEncodeFn(hexString: string): string {
|
||||
return hexString.split(' ')
|
||||
|
|
@ -60,7 +62,7 @@ function runTests() {
|
|||
testEncode('1111111111111111111111', '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00');
|
||||
testEncode('22222222222VtB5VXc', '\\x06\\x15\\x60\\x13\\x76\\x28\\x79\\xF7\\xFF\\xFF\\xFF\\xFF\\xFF');
|
||||
|
||||
const expectedAddress = 'ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH';
|
||||
const expectedAddress = 'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi';
|
||||
const dataToAddress: string = dataToEncodeFn(rawAddressBufferHex);
|
||||
testEncode(expectedAddress, dataToAddress);
|
||||
}
|
||||
|
|
@ -68,7 +70,7 @@ function runTests() {
|
|||
function runTestEncodeAddress(address: string, viewPubKey: string, spendPubKey: string): void {
|
||||
const addressBufferHex: string = dataToEncodeFn(bufferToHex(base58Decode(address)));
|
||||
testEncode(
|
||||
'ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH',
|
||||
'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi',
|
||||
addressBufferHex,
|
||||
);
|
||||
|
||||
|
|
@ -84,14 +86,14 @@ function runTestEncodeAddress(address: string, viewPubKey: string, spendPubKey:
|
|||
throw new Error('PubSpendKey not matched.');
|
||||
}
|
||||
|
||||
const encodedAddress: string = encodeAddress(197, 1, spendPubKey, viewPubKey);
|
||||
const encodedAddress: string = encodeAddress(ADDRESS_PREFIX, spendPubKey, viewPubKey);
|
||||
|
||||
if(encodedAddress !== address) {
|
||||
throw new Error(`Encoded address not matched. Received ${encodedAddress}, Expected: ${address}`);
|
||||
}
|
||||
}
|
||||
|
||||
function runTestGetZanoKeys(address: string, viewPubKey: string, spendPubKey: string): void {
|
||||
function runTestGetLetheanKeys(address: string, viewPubKey: string, spendPubKey: string): void {
|
||||
const keysFromAddress: ZarcanumAddressKeys = getKeysFromAddress(address);
|
||||
|
||||
if(keysFromAddress.spendPublicKey !== spendPubKey) {
|
||||
|
|
@ -106,12 +108,12 @@ function runTestGetZanoKeys(address: string, viewPubKey: string, spendPubKey: st
|
|||
void (async (): Promise<void> => {
|
||||
runTests();
|
||||
runTestEncodeAddress(
|
||||
'ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH',
|
||||
'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi',
|
||||
'a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3',
|
||||
'9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa',
|
||||
);
|
||||
runTestGetZanoKeys(
|
||||
'ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH',
|
||||
runTestGetLetheanKeys(
|
||||
'iTHNavWQHS59AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jL8ALnEwGMWi',
|
||||
'a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3',
|
||||
'9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ describe(
|
|||
const secretViewKey = '81ef6415b815f675991585ebba71c8c4663a08893fd93ee149c48e797a2fdf09';
|
||||
const publicSpendKey = '6be99667faa6b693fbcd808f94b8243540198c9cbb0b564f267f885d227804a2';
|
||||
|
||||
const integratedAddress = 'iZ285wzfsbjXYEgZVuDeFy74GFtYDFbvrFSJpL6TJQ3Z1mxZaKQLZsJHyVuCH4pQSr3rQunoH7cE4bjJSWmJqWSnKu6rPqXZ8HB1VxSHXVZR';
|
||||
const address = 'ZxCdxeu7oYRXYEgZVuDeFy74GFtYDFbvrFSJpL6TJQ3Z1mxZaKQLZsJHyVuCH4pQSr3rQunoH7cE4bjJSWmJqWSn1yGLxsfJH';
|
||||
const integratedAddress = 'iTHnPU9EtsKUtKxTWVi267XoQMNrbVzFk2tz6tmus8doM5KuSrewKQ2bMbwmzcBEhJGuGNwfPMnuxc6Rx5ZvvXroYMR846UJ1H4662LyVK6oo';
|
||||
const address = 'iTHNV7oXHXXUtKxTWVi267XoQMNrbVzFk2tz6tmus8doM5KuSrewKQ2bMbwmzcBEhJGuGNwfPMnuxc6Rx5ZvvXro86z84X5t3V';
|
||||
|
||||
it('checking the correctness of the result', () => {
|
||||
const result: DecodeTransactionResult = decodeTransaction(objectInJson, secretViewKey, publicSpendKey);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue