Skip to content

Commit

Permalink
Merge Dev: v1.1.0-3
Browse files Browse the repository at this point in the history
  • Loading branch information
Egge21M committed Aug 30, 2024
2 parents 4ddc1b1 + 4e4a5ad commit 669a012
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 62 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Supported token formats:
- [x] v1 read
- [x] v2 read (deprecated)
- [x] v3 read/write
- [x] v4 read/write

## Usage

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cashu/cashu-ts",
"version": "1.1.0-2",
"version": "1.1.0-3",
"description": "cashu library for communicating with a cashu mint",
"main": "dist/lib/es5/index.js",
"module": "dist/lib/es6/index.js",
Expand Down
74 changes: 33 additions & 41 deletions src/CashuWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,22 +130,18 @@ class CashuWallet {
privkey?: string;
}
): Promise<Array<Proof>> {
try {
if (typeof token === 'string') {
token = getDecodedToken(token);
}
const tokenEntries: Array<TokenEntry> = token.token;
const proofs = await this.receiveTokenEntry(tokenEntries[0], {
keysetId: options?.keysetId,
preference: options?.preference,
counter: options?.counter,
pubkey: options?.pubkey,
privkey: options?.privkey
});
return proofs;
} catch (error) {
throw new Error('Error when receiving');
if (typeof token === 'string') {
token = getDecodedToken(token);
}
const tokenEntries: Array<TokenEntry> = token.token;
const proofs = await this.receiveTokenEntry(tokenEntries[0], {
keysetId: options?.keysetId,
preference: options?.preference,
counter: options?.counter,
pubkey: options?.pubkey,
privkey: options?.privkey
});
return proofs;
}

/**
Expand All @@ -168,33 +164,29 @@ class CashuWallet {
}
): Promise<Array<Proof>> {
const proofs: Array<Proof> = [];
try {
const amount = tokenEntry.proofs.reduce((total, curr) => total + curr.amount, 0);
let preference = options?.preference;
if (!preference) {
preference = getDefaultAmountPreference(amount);
}
const keys = await this.getKeys(options?.keysetId);
const { payload, blindedMessages } = this.createSwapPayload(
amount,
tokenEntry.proofs,
keys,
preference,
options?.counter,
options?.pubkey,
options?.privkey
);
const { signatures } = await CashuMint.split(tokenEntry.mint, payload);
const newProofs = this.constructProofs(
signatures,
blindedMessages.rs,
blindedMessages.secrets,
keys
);
proofs.push(...newProofs);
} catch (error) {
throw new Error('Error receiving token entry');
const amount = tokenEntry.proofs.reduce((total, curr) => total + curr.amount, 0);
let preference = options?.preference;
if (!preference) {
preference = getDefaultAmountPreference(amount);
}
const keys = await this.getKeys(options?.keysetId);
const { payload, blindedMessages } = this.createSwapPayload(
amount,
tokenEntry.proofs,
keys,
preference,
options?.counter,
options?.pubkey,
options?.privkey
);
const { signatures } = await CashuMint.split(tokenEntry.mint, payload);
const newProofs = this.constructProofs(
signatures,
blindedMessages.rs,
blindedMessages.secrets,
keys
);
proofs.push(...newProofs);
return proofs;
}

Expand Down
80 changes: 65 additions & 15 deletions src/cbor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
type SimpleValue = boolean | null | undefined;

export type ResultObject = { [key: string]: ResultValue };
export type ResultValue =
| SimpleValue
| number
| string
| Uint8Array
| Array<ResultValue>
| ResultObject;

type ResultKeyType = Extract<ResultValue, number | string>;
export type ValidDecodedType = Extract<ResultValue, ResultObject>;

function isResultKeyType(value: ResultValue): value is ResultKeyType {
return typeof value === 'number' || typeof value === 'string';
}

type DecodeResult<T extends ResultValue> = {
value: T;
offset: number;
};

export function encodeCBOR(value: any) {
const buffer: Array<number> = [];
encodeItem(value, buffer);
Expand Down Expand Up @@ -119,18 +142,14 @@ function encodeObject(value: { [key: string]: any }, buffer: Array<number>) {
encodeItem(value[key], buffer);
}
}
type DecodeResult = {
value: any;
offset: number;
};

export function decodeCBOR(data: Uint8Array): any {
export function decodeCBOR(data: Uint8Array): ResultValue {
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const result = decodeItem(view, 0);
return result.value;
}

function decodeItem(view: DataView, offset: number): DecodeResult {
function decodeItem(view: DataView, offset: number): DecodeResult<ResultValue> {
if (offset >= view.byteLength) {
throw new Error('Unexpected end of data');
}
Expand Down Expand Up @@ -158,7 +177,11 @@ function decodeItem(view: DataView, offset: number): DecodeResult {
}
}

function decodeLength(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeLength(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<number> {
if (additionalInfo < 24) return { value: additionalInfo, offset };
if (additionalInfo === 24) return { value: view.getUint8(offset++), offset };
if (additionalInfo === 25) {
Expand All @@ -180,17 +203,29 @@ function decodeLength(view: DataView, offset: number, additionalInfo: number): D
throw new Error(`Unsupported length: ${additionalInfo}`);
}

function decodeUnsigned(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeUnsigned(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<number> {
const { value, offset: newOffset } = decodeLength(view, offset, additionalInfo);
return { value, offset: newOffset };
}

function decodeSigned(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeSigned(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<number> {
const { value, offset: newOffset } = decodeLength(view, offset, additionalInfo);
return { value: -1 - value, offset: newOffset };
}

function decodeByteString(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeByteString(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<Uint8Array> {
const { value: length, offset: newOffset } = decodeLength(view, offset, additionalInfo);
if (newOffset + length > view.byteLength) {
throw new Error('Byte string length exceeds data length');
Expand All @@ -199,7 +234,11 @@ function decodeByteString(view: DataView, offset: number, additionalInfo: number
return { value, offset: newOffset + length };
}

function decodeString(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeString(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<string> {
const { value: length, offset: newOffset } = decodeLength(view, offset, additionalInfo);
if (newOffset + length > view.byteLength) {
throw new Error('String length exceeds data length');
Expand All @@ -209,7 +248,11 @@ function decodeString(view: DataView, offset: number, additionalInfo: number): D
return { value, offset: newOffset + length };
}

function decodeArray(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeArray(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<Array<ResultValue>> {
const { value: length, offset: newOffset } = decodeLength(view, offset, additionalInfo);
const array = [];
let currentOffset = newOffset;
Expand All @@ -221,12 +264,19 @@ function decodeArray(view: DataView, offset: number, additionalInfo: number): De
return { value: array, offset: currentOffset };
}

function decodeMap(view: DataView, offset: number, additionalInfo: number): DecodeResult {
function decodeMap(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult<Record<string, ResultValue>> {
const { value: length, offset: newOffset } = decodeLength(view, offset, additionalInfo);
const map: { [key: string]: any } = {};
const map: { [key: string]: ResultValue } = {};
let currentOffset = newOffset;
for (let i = 0; i < length; i++) {
const keyResult = decodeItem(view, currentOffset);
if (!isResultKeyType(keyResult.value)) {
throw new Error('Invalid key type');
}
const valueResult = decodeItem(view, keyResult.offset);
map[keyResult.value] = valueResult.value;
currentOffset = valueResult.offset;
Expand All @@ -251,7 +301,7 @@ function decodeSimpleAndFloat(
view: DataView,
offset: number,
additionalInfo: number
): DecodeResult {
): DecodeResult<SimpleValue | number> {
if (additionalInfo < 24) {
switch (additionalInfo) {
case 20:
Expand Down
2 changes: 1 addition & 1 deletion test/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ describe('mint api', () => {
const result = await wallet
.receive(encoded, { privkey: bytesToHex(privKeyAlice) })
.catch((e) => e);
expect(result).toEqual(new Error('Error when receiving'));
expect(result).toEqual(new Error('no valid signature provided for input.'));

const proofs = await wallet.receive(encoded, { privkey: bytesToHex(privKeyBob) });

Expand Down
4 changes: 2 additions & 2 deletions test/wallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ describe('receive', () => {
nock(mintUrl).post('/v1/swap').reply(400, { detail: msg });
const wallet = new CashuWallet(mint, { unit });
const result = await wallet.receive(tokenInput).catch((e) => e);
expect(result).toEqual(new Error('Error when receiving'));
expect(result).toEqual(new Error('tokens already spent. Secret: asdasdasd'));
});

test('test receive could not verify proofs', async () => {
nock(mintUrl).post('/v1/swap').reply(400, { code: 0, error: 'could not verify proofs.' });
const wallet = new CashuWallet(mint, { unit });
const result = await wallet.receive(tokenInput).catch((e) => e);
expect(result).toEqual(new Error('Error when receiving'));
expect(result).toEqual(new Error('could not verify proofs.'));
});
});

Expand Down

0 comments on commit 669a012

Please sign in to comment.