Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
c57a408
WASM version bump + updated examples
Gohlub Feb 26, 2026
d19184e
hotfix for modules not relevant to this PR
Gohlub Feb 26, 2026
03c6a1d
version bump again + new export style
Gohlub Mar 1, 2026
2c1f8a8
got rid of undefined
Gohlub Mar 1, 2026
cd56208
compatibility for Nicks in all potential formats
Gohlub Mar 1, 2026
ecc60e4
add support for native and legacy signtx
Gohlub Mar 4, 2026
22d1766
concrete type for legacy transaction signing
Gohlub Mar 4, 2026
199f26a
fix examples
Gohlub Mar 5, 2026
34c9e70
fixes according to comments, added guard export
Gohlub Mar 5, 2026
1a806bf
Update package.lock
h33p Mar 5, 2026
f6b1935
Fix examples
h33p Mar 5, 2026
e0320cd
Bump version
h33p Mar 5, 2026
e9adb62
Update iris-wasm
h33p Mar 5, 2026
faaf42b
bump iris-wasm to alpha.6
Gohlub Mar 10, 2026
5679411
added APIs for v0 to v1 migration and swap (bridge) to be consumed by…
Gohlub Feb 26, 2026
61bea2e
temporary WASM module
Gohlub Mar 1, 2026
e3fd27e
update migration
Gohlub Mar 2, 2026
940bd48
refactored and simplified the migration logic and the SDK API
Gohlub Mar 3, 2026
8d0c8ca
temporary commit for testing: use the smallest note for migration
Gohlub Mar 4, 2026
079f535
add spend condition to the rebuilt transaction to satisfy the API
Gohlub Mar 4, 2026
dc5101c
fix RPC
Gohlub Mar 4, 2026
c0101ac
Remove vendor/iris-wasm from package, add vendor/ to gitignore
Gohlub Mar 9, 2026
2b989a8
update iris-wasm API calls
Gohlub Mar 10, 2026
2bb34b4
clean up migration logic
Gohlub Mar 11, 2026
82e165e
update and fix bridging logic
Gohlub Mar 12, 2026
1cbf49e
Define RPC API V1 and switch SDK to it
h33p Mar 20, 2026
afb60e5
Merge pull request #4 from nockbox/api-v1
Gohlub Mar 25, 2026
31a973d
use new API, fix issues with parsing Nicks
Gohlub Mar 26, 2026
386ccd3
Merge branch 'feat/wasm-module-version-bump' into feat/sdk-v0-and-bri…
Gohlub Mar 26, 2026
8c7cd68
Merge pull request #2 from nockbox/feat/sdk-v0-and-bridge-APIs
Gohlub Mar 26, 2026
d7140b0
update bridge for parsing new pkh digest format
Gohlub Mar 26, 2026
2653e43
build sdk upon install
Gohlub Mar 26, 2026
abd99a2
move constant to constants
Gohlub Apr 8, 2026
bd4fcad
add type guard and change derivedV0address to public key
Gohlub Apr 8, 2026
5c998dd
change signatures to accept public keys instead of deriving internally
Gohlub Apr 8, 2026
a3ba39f
add tx engine as a required parameter, change debug to be specific to…
Gohlub Apr 8, 2026
7e13cca
add options for bridge to get tx engine settings from the caller
Gohlub Apr 15, 2026
0ee3503
fix comment
Gohlub Apr 15, 2026
1c3741a
define default coinbase inside of SDK
Gohlub Apr 15, 2026
420f43b
add sign-tx-request guard in the SDK
Gohlub Apr 15, 2026
b0f132c
more consolidation
Gohlub Apr 15, 2026
aa27550
add default activation height to sdk
Gohlub Apr 15, 2026
0e3aa87
enforce a clearer API: v0 transaction building not used anymore for b…
Gohlub Apr 15, 2026
9feb057
moved config INTO SDK
Gohlub Apr 15, 2026
d02a12e
depract api in connection request since RPC request now holds it
Gohlub Apr 15, 2026
ef3d324
expose internal helpers to fit the extension better, add legacy path …
Gohlub Apr 15, 2026
5cce6f6
formatting, small API change, update package.json to not export guard…
Gohlub Apr 15, 2026
c2a06a1
fix examples, add small helper
Gohlub Apr 15, 2026
c9874cd
connect fix
Gohlub Apr 15, 2026
6762b9d
add guard to sign_message provider method
Gohlub Apr 15, 2026
734896f
bridge debugging + hotfix for spend condition index
Gohlub Apr 15, 2026
056c907
hotfix for bridge and logs
Gohlub Apr 15, 2026
1ec925c
replicate nockswap
Gohlub Apr 15, 2026
087d141
fix atom decoding for bridge logic
Gohlub Apr 20, 2026
7d0bc1c
pick smallest note that is larger than 100 nocks for debug
Gohlub Apr 23, 2026
94a8fc0
fix response type for legacy API request shapes
Gohlub Apr 23, 2026
5daf5b0
display input notes properly on legacy sign raw tx request
Gohlub Apr 23, 2026
8a5e47e
use smallest 2 notes with more than 100 nocks total
Gohlub Apr 23, 2026
a2caf78
fix: remove redundant guard: extension only returns modern format
Gohlub Apr 27, 2026
562b61e
more informative comments
Gohlub Apr 28, 2026
62c67a8
fix example to use tx engine settings from provider
Gohlub Apr 28, 2026
cae86c6
clarify tx builder output preview comment
Gohlub Apr 28, 2026
049ef0c
fix edge case of a silent fail when the note amount isn't enough yet …
Gohlub Apr 28, 2026
06901ae
format
Gohlub Apr 28, 2026
4406861
remove stringtoatoms method
Gohlub Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ lib/nbx-wasm
# Build output
dist/
examples-dist/
vendor/

# TypeScript
*.tsbuildinfo
Expand Down
105 changes: 49 additions & 56 deletions examples/app.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NockchainProvider, wasm } from '../src/index';
import { NockchainProvider, getLatestTxEngineSettings, wasm } from '../src/index';

const statusDiv = document.getElementById('status')!;
const outputPre = document.getElementById('output')!;
Expand All @@ -9,6 +9,15 @@ const recipientInput = document.getElementById('recipientInput') as HTMLInputEle
let provider: NockchainProvider;
let grpcEndpoint: string | null = null;
let walletPkh: string | null = null;
let txEngineSettings = getLatestTxEngineSettings();

function asDigest(value: string): wasm.Digest {
return value as wasm.Digest;
}

function asNicks(value: string): wasm.Nicks {
return value as wasm.Nicks;
}

function log(msg: string) {
outputPre.textContent += msg + '\n';
Expand All @@ -34,10 +43,11 @@ connectBtn.onclick = async () => {
return;
}
try {
// Connect to wallet (returns pkh and grpcEndpoint)
// Connect to wallet
const info = await provider.connect();
grpcEndpoint = info.grpcEndpoint;
walletPkh = info.pkh;
grpcEndpoint = info.rpcConfig.rpcUrl;
walletPkh = info.account.address;
txEngineSettings = getLatestTxEngineSettings(info.rpcConfig.txEngineActivationHeights);

statusDiv.textContent = 'Connected: ' + walletPkh;
signRawTxBtn.disabled = false;
Expand Down Expand Up @@ -67,18 +77,13 @@ signRawTxBtn.onclick = async () => {
log('Creating gRPC client for: ' + grpcEndpoint);
const grpcClient = new wasm.GrpcClient(grpcEndpoint);

// 3. Create spend condition using wallet PKH (single, no timelock)
log('Creating spend condition for PKH: ' + walletPkh);
const pkh = wasm.Pkh.single(walletPkh);
const spendCondition = wasm.SpendCondition.newPkh(pkh);

// 4. Get firstName from spend condition
const firstName = spendCondition.firstName();
log('First name: ' + firstName.value.substring(0, 20) + '...');

// 5. Query notes matching this firstName
log('Querying notes from gRPC...');
const balance = await grpcClient.getBalanceByFirstName(firstName.value);
// 3. Derive first-name from PKH and query notes (notes are indexed by first-name, not address)
const spendCondition: wasm.SpendCondition = [
{ tag: 'pkh', m: 1, hashes: [asDigest(walletPkh)] },
];
const firstName = wasm.spendConditionFirstName(spendCondition);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iris-wasm needs to have lockFirstName, rather than spendConditionFirstName

log('Querying notes by first-name...');
const balance = await grpcClient.getBalanceByFirstName(firstName);

if (!balance || !balance.notes || balance.notes.length === 0) {
log('No notes found - wallet might be empty');
Expand All @@ -87,76 +92,64 @@ signRawTxBtn.onclick = async () => {

log('Found ' + balance.notes.length + ' notes');

// Convert notes from protobuf
const notes = balance.notes.map((n: any) => wasm.Note.fromProtobuf(n.note));
// Convert notes from protobuf (0.2: free function)
const notes = balance.notes
.map((entry: any) => entry.note)
.filter(Boolean)
.map((noteProto: wasm.PbCom2Note) => wasm.noteFromProtobuf(noteProto));

if (!notes.length) {
log('No parseable notes found');
return;
}

const note = notes[0];
const noteAssets = note.assets;
log('Using note with ' + noteAssets + ' nicks');

// 6. Build transaction (send 10 NOCK = 655360 nicks)
const TEN_NOCK_IN_NICKS = BigInt(10 * 65536);
const feePerWord = BigInt(32768); // 0.5 NOCK per word
// 4. Build transaction (send 10 NOCK = 655360 nicks)
const TEN_NOCK_IN_NICKS = asNicks(String(10 * 65536));

log('Building transaction to send 10 NOCK...');
const builder = new wasm.TxBuilder(feePerWord);

// Create recipient digest
const recipientDigest = new wasm.Digest(recipient);

// Create refund digest (same as wallet PKH)
const refundDigest = new wasm.Digest(walletPkh);
const builder = new wasm.TxBuilder(txEngineSettings);

// Use simpleSpend (no lockData for lower fees)
// Use simpleSpend (no lockData for lower fees), digest values are strings in 0.2
builder.simpleSpend(
[notes[0]],
[spendCondition],
recipientDigest,
[note],
[spendCondition as unknown as wasm.TxLock],
asDigest(recipient),
TEN_NOCK_IN_NICKS,
null, // fee_override (let it auto-calculate)
refundDigest,
asDigest(walletPkh),
false // include_lock_data
);

// 7. Build the transaction and get notes/spend conditions
// 5. Build the transaction and get notes/spend conditions
log('Building raw transaction...');
const nockchainTx = builder.build();
const txId = nockchainTx.id;
log('Transaction ID: ' + txId.value);
log('Transaction ID: ' + txId);

const rawTxProtobuf = nockchainTx.toRawTx().toProtobuf();

// Get notes and spend conditions from builder
const txNotes = builder.allNotes();

log('Notes count: ' + txNotes.notes.length);
log('Spend conditions count: ' + txNotes.spendConditions.length);

// 8. Sign using provider.signRawTx (pass wasm objects directly)
// 6. Sign using provider.signTx
log('Signing transaction...');
const signedTxProtobuf = await provider.signRawTx({
rawTx: rawTxProtobuf, // Pass wasm RawTx directly
notes: txNotes.notes, // Pass wasm Note objects directly
spendConditions: txNotes.spendConditions, // Pass wasm SpendCondition objects directly
});
const signed = await provider.signTx(nockchainTx);

log('Transaction signed successfully!');

// Convert to jam string for file download
const signedTx = wasm.RawTx.fromProtobuf(signedTxProtobuf);
const jamBytes = signedTx.toJam();

// 9. Download to file using transaction ID
// 7. Convert signed tx to Jam and download
const signedRawTx = wasm.nockchainTxToRawTx(signed.tx as any);
const jamBytes = wasm.jam(signedRawTx as unknown as wasm.Noun);
const blob = new Blob([new Uint8Array(jamBytes)], { type: 'application/jam' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${txId.value}.tx`;
a.download = `${txId}.tx`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);

log('Downloaded transaction to file: ' + txId.value + '.tx');
log('Downloaded signed transaction (Jam): ' + txId + '.tx');
} catch (e: any) {
log('Error: ' + e.message);
console.error(e);
Expand Down
Loading
Loading