ci: docker_tag=ext | use prebuilt wasm pkg (no wasm build in CI)
All checks were successful
Build and Push Docker image (ext) / docker (push) Successful in 52s
All checks were successful
Build and Push Docker image (ext) / docker (push) Successful in 52s
This commit is contained in:
parent
653b86fbc9
commit
a4dd8c57f2
53
Dockerfile
53
Dockerfile
@ -1,62 +1,11 @@
|
||||
# syntax=docker/dockerfile:1.4
|
||||
FROM rust:1.82-alpine AS wasm-builder
|
||||
WORKDIR /build
|
||||
|
||||
# Installation des dépendances nécessaires pour la compilation
|
||||
RUN apk update && apk add --no-cache \
|
||||
git \
|
||||
openssh-client \
|
||||
curl \
|
||||
nodejs \
|
||||
npm \
|
||||
build-base \
|
||||
pkgconfig \
|
||||
clang \
|
||||
llvm \
|
||||
musl-dev \
|
||||
nginx
|
||||
|
||||
# Installer wasm-bindgen CLI (0.2.92) et target wasm32 (Rust >=1.81)
|
||||
RUN cargo install wasm-bindgen-cli --version 0.2.103 --locked && \
|
||||
rustup target add wasm32-unknown-unknown
|
||||
ENV PATH="/usr/local/cargo/bin:${PATH}"
|
||||
|
||||
# Configuration SSH basique
|
||||
RUN mkdir -p /root/.ssh && \
|
||||
ssh-keyscan git.4nkweb.com >> /root/.ssh/known_hosts
|
||||
|
||||
# On se place dans le bon répertoire parent
|
||||
WORKDIR /build
|
||||
# Copie du projet ihm_client
|
||||
COPY . ihm_client/
|
||||
|
||||
# Clonage du sdk_client au même niveau que ihm_client en utilisant la clé SSH montée
|
||||
RUN --mount=type=ssh git clone -b dev ssh://git@git.4nkweb.com/4nk/sdk_client.git
|
||||
|
||||
# Build du WebAssembly (cargo) + wasm-bindgen
|
||||
WORKDIR /build/sdk_client
|
||||
# Harmoniser wasm-bindgen crate avec le CLI
|
||||
RUN cargo update -p wasm-bindgen --precise 0.2.103 && \
|
||||
cargo update -p wasm-bindgen-macro --precise 0.2.103 && \
|
||||
cargo update -p wasm-bindgen-backend --precise 0.2.103 && \
|
||||
cargo update -p wasm-bindgen-macro-support --precise 0.2.103 && \
|
||||
cargo update -p js-sys --precise 0.3.80 && \
|
||||
cargo update -p web-sys --precise 0.3.80 && \
|
||||
cargo build --target wasm32-unknown-unknown --profile dev && \
|
||||
wasm-bindgen target/wasm32-unknown-unknown/debug/sdk_client.wasm \
|
||||
--out-dir /build/ihm_client/pkg \
|
||||
--typescript \
|
||||
--target bundler \
|
||||
--debug
|
||||
|
||||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
|
||||
# Installation des dépendances nécessaires
|
||||
RUN apk update && apk add --no-cache git nginx
|
||||
|
||||
# Copie des fichiers du projet
|
||||
COPY --from=wasm-builder /build/ihm_client/pkg ./pkg
|
||||
# Copie du projet (incluant pkg pré-compilé)
|
||||
COPY . .
|
||||
|
||||
# Installation des dépendances Node.js
|
||||
|
34
pkg/README.md
Normal file
34
pkg/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
## sdk_client — bibliothèque cliente Silent Payments (WASM)
|
||||
|
||||
Ce dépôt fournit une bibliothèque cliente visant l’intégration WebAssembly pour gérer appareil, portefeuille, processus et échanges chiffrés associés aux Silent Payments. Cette documentation renvoie vers `docs/` pour les spécifications détaillées, sans exemples exécutables.
|
||||
|
||||
## 📋 Table des Matières
|
||||
|
||||
- [📚 Documentation](#-documentation)
|
||||
- [🧪 Tests](#-tests)
|
||||
- [🛠️ Développement](#️-développement)
|
||||
- [🚨 Dépannage](#-dépannage)
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- [Architecture](docs/ARCHITECTURE.md)
|
||||
- [Référence API](docs/API.md)
|
||||
- [Configuration](docs/CONFIGURATION.md)
|
||||
- [Tests](docs/TESTING.md)
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
- Tests natifs: `cargo test`
|
||||
- Tests WASM (Windows): utiliser le script PowerShell `scripts/run-wasm-tests.ps1` (prérequis LLVM/Clang, voir `docs/TESTING.md`).
|
||||
|
||||
## 🛠️ Développement
|
||||
|
||||
La surface de code est centrée sur `src/` (Rust) avec export WASM. Les invariants sont décrits dans `docs/ARCHITECTURE.md` et `docs/API.md`.
|
||||
|
||||
## 🚨 Dépannage
|
||||
|
||||
Consulter `docs/TESTING.md` (section WASM Windows) pour les variables d’environnement et le runner wasm-bindgen.
|
||||
|
||||
---
|
||||
|
||||
Documentation de référence: voir `docs/` pour la table des matières.
|
11
pkg/package.json
Normal file
11
pkg/package.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "sdk_client",
|
||||
"version": "0.1.3",
|
||||
"files": [
|
||||
"sdk_client_bg.wasm",
|
||||
"sdk_client.js",
|
||||
"sdk_client.d.ts"
|
||||
],
|
||||
"main": "sdk_client.js",
|
||||
"types": "sdk_client.d.ts"
|
||||
}
|
248
pkg/sdk_client.d.ts
vendored
Normal file
248
pkg/sdk_client.d.ts
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export function setup(): void;
|
||||
export function get_address(): string;
|
||||
export function get_member(): Member;
|
||||
export function restore_device(device: any): void;
|
||||
export function create_device_from_sp_wallet(sp_wallet: string): string;
|
||||
export function create_new_device(birthday: number, network_str: string): string;
|
||||
export function scan_blocks(tip_height: number, blindbit_url: string): Promise<void>;
|
||||
export function is_paired(): boolean;
|
||||
export function pair_device(process_id: string, sp_addresses: string[]): void;
|
||||
export function unpair_device(): void;
|
||||
export function dump_wallet(): string;
|
||||
export function reset_shared_secrets(): void;
|
||||
export function set_shared_secrets(secrets: string): void;
|
||||
export function get_pairing_process_id(): string;
|
||||
export function dump_device(): Device;
|
||||
export function dump_neutered_device(): Device;
|
||||
export function reset_device(): void;
|
||||
export function get_txid(transaction: string): string;
|
||||
export function get_prevouts(transaction: string): string[];
|
||||
export function get_opreturn(transaction: string): string;
|
||||
export function process_commit_new_state(process: Process, state_id: string, new_tip: string): Process;
|
||||
export function parse_new_tx(new_tx_msg: string, block_height: number, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function parse_cipher(cipher_msg: string, members_list: OutPointMemberMap, processes: OutPointProcessMap): ApiReturn;
|
||||
export function get_outputs(): any;
|
||||
export function get_available_amount(): bigint;
|
||||
/**
|
||||
* We send a transaction that pays at least one output to each address
|
||||
* The goal can be to establish a shared_secret to be used as an encryption key for further communication
|
||||
* or if the recipient is a relay it can be the init transaction for a new process
|
||||
*/
|
||||
export function create_transaction(addresses: string[], fee_rate: number): ApiReturn;
|
||||
export function sign_transaction(partial_tx: TsUnsignedTransaction): ApiReturn;
|
||||
export function create_new_process(private_data: Pcd, roles: Roles, public_data: Pcd, relay_address: string, fee_rate: number, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function update_process(process: Process, new_attributes: Pcd, roles: Roles, new_public_data: Pcd, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function request_data(process_id: string, state_ids_str: string[], roles: any, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function create_update_message(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function validate_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function refuse_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function evaluate_state(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function create_response_prd(process: Process, state_id: string, members_list: OutPointMemberMap): ApiReturn;
|
||||
export function create_faucet_msg(): string;
|
||||
export function get_storages(process_outpoint: string): string[];
|
||||
export function is_child_role(parent_roles: string, child_roles: string): void;
|
||||
export function decrypt_data(key: Uint8Array, data: Uint8Array): Uint8Array;
|
||||
export function encode_binary(data: any): Pcd;
|
||||
export function encode_json(json_data: any): Pcd;
|
||||
export function decode_value(value: Uint8Array): any;
|
||||
export function hash_value(value: any, commited_in: string, label: string): string;
|
||||
/**
|
||||
* Generate a merkle proof for a specific attribute in a process state.
|
||||
*
|
||||
* This function creates a merkle proof that proves the existence of a specific attribute
|
||||
* in a given state of a process. The proof can be used to verify that the attribute
|
||||
* was indeed part of the state without revealing the entire state.
|
||||
*
|
||||
* # Arguments
|
||||
* * `process_state` - The process state object as a JavaScript value
|
||||
* * `attribute_name` - The name of the attribute to generate a proof for
|
||||
*
|
||||
* # Returns
|
||||
* A MerkleProofResult object containing:
|
||||
* * `proof` - The merkle proof as a hex string
|
||||
* * `root` - The merkle root (state_id) as a hex string
|
||||
* * `attribute` - The attribute name that was proven
|
||||
* * `attribute_index` - The index of the attribute in the merkle tree
|
||||
* * `total_leaves_count` - The total number of leaves in the merkle tree
|
||||
*
|
||||
* # Errors
|
||||
* * "Failed to deserialize process state" - If the process state cannot be deserialized from JsValue
|
||||
* * "Attribute not found in state" - If the attribute doesn't exist in the state
|
||||
*/
|
||||
export function get_merkle_proof(process_state: any, attribute_name: string): MerkleProofResult;
|
||||
/**
|
||||
* Validate a merkle proof for a specific attribute.
|
||||
*
|
||||
* This function verifies that a merkle proof is valid and proves the existence
|
||||
* of a specific attribute in a given state. It checks that the proof correctly
|
||||
* leads to the claimed root when combined with the attribute hash.
|
||||
*
|
||||
* # Arguments
|
||||
* * `proof_result` - a JsValue expected to contain a MerkleProofResult with the proof and metadata
|
||||
* * `hash` - The hash of the attribute data as a hex string (the leaf value)
|
||||
*
|
||||
* # Returns
|
||||
* A boolean indicating whether the proof is valid
|
||||
*
|
||||
* # Errors
|
||||
* * "serde_wasm_bindgen deserialization error" - If the proof is not a valid MerkleProofResult
|
||||
* * "Invalid proof format" - If the proof cannot be parsed
|
||||
* * "Invalid hash format" - If the hash is not a valid 32-byte hex string
|
||||
* * "Invalid root format" - If the root is not a valid 32-byte hex string
|
||||
*/
|
||||
export function validate_merkle_proof(proof_result: any, hash: string): boolean;
|
||||
export type DiffStatus = "None" | "Rejected" | "Validated";
|
||||
|
||||
export interface UserDiff {
|
||||
process_id: string;
|
||||
state_id: string;
|
||||
value_commitment: string;
|
||||
field: string;
|
||||
roles: Roles;
|
||||
description: string | null;
|
||||
notify_user: boolean;
|
||||
need_validation: boolean;
|
||||
validation_status: DiffStatus;
|
||||
}
|
||||
|
||||
export interface UpdatedProcess {
|
||||
process_id: OutPoint;
|
||||
current_process: Process;
|
||||
diffs: UserDiff[];
|
||||
encrypted_data: Record<string, string>;
|
||||
validated_state: number[] | null;
|
||||
}
|
||||
|
||||
export interface ApiReturn {
|
||||
secrets: SecretsStore | null;
|
||||
updated_process: UpdatedProcess | null;
|
||||
new_tx_to_send: NewTxMessage | null;
|
||||
ciphers_to_send: string[];
|
||||
commit_to_send: CommitMessage | null;
|
||||
push_to_storage: string[];
|
||||
partial_tx: TsUnsignedTransaction | null;
|
||||
}
|
||||
|
||||
export interface encryptWithNewKeyResult {
|
||||
cipher: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface MerkleProofResult {
|
||||
proof: string;
|
||||
root: string;
|
||||
attribute: string;
|
||||
attribute_index: number;
|
||||
total_leaves_count: number;
|
||||
}
|
||||
|
||||
export interface Device {
|
||||
sp_wallet: SpWallet;
|
||||
pairing_process_commitment: OutPoint | null;
|
||||
paired_member: Member;
|
||||
}
|
||||
|
||||
export interface SecretsStore {
|
||||
shared_secrets: Record<SilentPaymentAddress, AnkSharedSecretHash>;
|
||||
unconfirmed_secrets: AnkSharedSecretHash[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A process is basically a succession of states
|
||||
* The latest state MUST be an empty state with only the commited_in field set at the last unspent outpoint
|
||||
* Commiting this last empty state in a transaction is called obliterating a process, basically terminating it
|
||||
*/
|
||||
export interface Process {
|
||||
states: ProcessState[];
|
||||
}
|
||||
|
||||
export interface ProcessState {
|
||||
commited_in: OutPoint;
|
||||
pcd_commitment: Record<string, string>;
|
||||
state_id: string;
|
||||
keys: Record<string, string>;
|
||||
validation_tokens: Proof[];
|
||||
public_data: Pcd;
|
||||
roles: Record<string, RoleDefinition>;
|
||||
}
|
||||
|
||||
export type Roles = Record<string, RoleDefinition>;
|
||||
|
||||
export interface RoleDefinition {
|
||||
members: OutPoint[];
|
||||
validation_rules: ValidationRule[];
|
||||
storages: string[];
|
||||
}
|
||||
|
||||
export interface ValidationRule {
|
||||
quorum: number;
|
||||
fields: string[];
|
||||
min_sig_member: number;
|
||||
}
|
||||
|
||||
export type PcdCommitments = Record<string, string>;
|
||||
|
||||
export type Pcd = Record<string, number[]>;
|
||||
|
||||
export interface Member {
|
||||
sp_addresses: string[];
|
||||
}
|
||||
|
||||
export type TsUnsignedTransaction = SilentPaymentUnsignedTransaction;
|
||||
|
||||
export type OutPointProcessMap = Record<OutPoint, Process>;
|
||||
|
||||
export type OutPointMemberMap = Record<OutPoint, Member>;
|
||||
|
||||
export interface Prd {
|
||||
prd_type: PrdType;
|
||||
process_id: OutPoint;
|
||||
sender: OutPoint | null;
|
||||
keys: Record<string, number[]>;
|
||||
pcd_commitments: PcdCommitments;
|
||||
validation_tokens: Proof[];
|
||||
roles: Roles;
|
||||
public_data: Pcd;
|
||||
payload: string;
|
||||
proof: Proof | null;
|
||||
}
|
||||
|
||||
export type PrdType = "None" | "Connect" | "Message" | "Update" | "List" | "Response" | "Confirm" | "TxProposal" | "Request";
|
||||
|
||||
export interface HandshakeMessage {
|
||||
sp_address: string;
|
||||
peers_list: OutPointMemberMap;
|
||||
processes_list: OutPointProcessMap;
|
||||
chain_tip: number;
|
||||
}
|
||||
|
||||
export interface NewTxMessage {
|
||||
transaction: string;
|
||||
tweak_data: string | null;
|
||||
error: AnkError | null;
|
||||
}
|
||||
|
||||
export interface FaucetMessage {
|
||||
sp_address: string;
|
||||
commitment: string;
|
||||
error: AnkError | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message sent to the server to commit some state in a transaction
|
||||
* Client must first send a commit message with empty validation_tokens
|
||||
* Relay will ignore a commit message for an update he\'s not aware of that also bears validation_tokens
|
||||
*/
|
||||
export interface CommitMessage {
|
||||
process_id: OutPoint;
|
||||
pcd_commitment: PcdCommitments;
|
||||
roles: Roles;
|
||||
public_data: Pcd;
|
||||
validation_tokens: Proof[];
|
||||
error: AnkError | null;
|
||||
}
|
||||
|
||||
export type AnkFlag = "NewTx" | "Faucet" | "Cipher" | "Commit" | "Handshake" | "Sync" | "Unknown";
|
||||
|
1672
pkg/sdk_client.js
Normal file
1672
pkg/sdk_client.js
Normal file
File diff suppressed because it is too large
Load Diff
BIN
pkg/sdk_client_bg.wasm
Normal file
BIN
pkg/sdk_client_bg.wasm
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user