mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
feat: create organizedProofs function
test: organizedProofs function
This commit is contained in:
parent
ac684194a0
commit
61cc7c335a
2 changed files with 158 additions and 2 deletions
|
|
@ -5,7 +5,7 @@ import { assertEquals } from '@std/assert';
|
||||||
|
|
||||||
import { createTestDB, genEvent } from '@/test.ts';
|
import { createTestDB, genEvent } from '@/test.ts';
|
||||||
|
|
||||||
import { validateAndParseWallet } from '@/utils/cashu.ts';
|
import { organizeProofs, validateAndParseWallet } from '@/utils/cashu.ts';
|
||||||
|
|
||||||
Deno.test('validateAndParseWallet function returns valid data', async () => {
|
Deno.test('validateAndParseWallet function returns valid data', async () => {
|
||||||
await using db = await createTestDB({ pure: true });
|
await using db = await createTestDB({ pure: true });
|
||||||
|
|
@ -51,3 +51,119 @@ Deno.test('validateAndParseWallet function returns valid data', async () => {
|
||||||
mints: ['https://mint.soul.com'],
|
mints: ['https://mint.soul.com'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test('organizeProofs function is working', async () => {
|
||||||
|
await using db = await createTestDB({ pure: true });
|
||||||
|
const store = db.store;
|
||||||
|
|
||||||
|
const sk = generateSecretKey();
|
||||||
|
const signer = new NSecSigner(sk);
|
||||||
|
const pubkey = await signer.getPublicKey();
|
||||||
|
|
||||||
|
const event1 = genEvent({
|
||||||
|
kind: 7375,
|
||||||
|
content: await signer.nip44.encrypt(
|
||||||
|
pubkey,
|
||||||
|
JSON.stringify({
|
||||||
|
mint: 'https://mint.soul.com',
|
||||||
|
proofs: [
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
del: [],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}, sk);
|
||||||
|
await db.store.event(event1);
|
||||||
|
|
||||||
|
const proof1 = {
|
||||||
|
'id': '004f7adf2a04356c',
|
||||||
|
'amount': 1,
|
||||||
|
'secret': '6780378b186cf7ada639ce4807803ad5e4a71217688430512f35074f9bca99c0',
|
||||||
|
'C': '03f0dd8df04427c8c53e4ae9ce8eb91c4880203d6236d1d745c788a5d7a47aaff3',
|
||||||
|
'dleq': {
|
||||||
|
'e': 'bd22fcdb7ede1edb52b9b8c6e1194939112928e7b4fc0176325e7671fb2bd351',
|
||||||
|
's': 'a9ad015571a0e538d62966a16d2facf806fb956c746a3dfa41fa689486431c67',
|
||||||
|
'r': 'b283980e30bf5a31a45e5e296e93ae9f20bf3a140c884b3b4cd952dbecc521df',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const token1 = JSON.stringify({
|
||||||
|
mint: 'https://mint-fashion.com',
|
||||||
|
proofs: [proof1],
|
||||||
|
del: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const event2 = genEvent({
|
||||||
|
kind: 7375,
|
||||||
|
content: await signer.nip44.encrypt(
|
||||||
|
pubkey,
|
||||||
|
token1,
|
||||||
|
),
|
||||||
|
}, sk);
|
||||||
|
await db.store.event(event2);
|
||||||
|
|
||||||
|
const proof2 = {
|
||||||
|
'id': '004f7adf2a04356c',
|
||||||
|
'amount': 123,
|
||||||
|
'secret': '6780378b186cf7ada639ce4807803ad5e4a71217688430512f35074f9bca99c0',
|
||||||
|
'C': '03f0dd8df04427c8c53e4ae9ce8eb91c4880203d6236d1d745c788a5d7a47aaff3',
|
||||||
|
'dleq': {
|
||||||
|
'e': 'bd22fcdb7ede1edb52b9b8c6e1194939112928e7b4fc0176325e7671fb2bd351',
|
||||||
|
's': 'a9ad015571a0e538d62966a16d2facf806fb956c746a3dfa41fa689486431c67',
|
||||||
|
'r': 'b283980e30bf5a31a45e5e296e93ae9f20bf3a140c884b3b4cd952dbecc521df',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const token2 = JSON.stringify({
|
||||||
|
mint: 'https://mint-fashion.com',
|
||||||
|
proofs: [proof2],
|
||||||
|
del: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const event3 = genEvent({
|
||||||
|
kind: 7375,
|
||||||
|
content: await signer.nip44.encrypt(
|
||||||
|
pubkey,
|
||||||
|
token2,
|
||||||
|
),
|
||||||
|
}, sk);
|
||||||
|
await db.store.event(event3);
|
||||||
|
|
||||||
|
const unspentProofs = await store.query([{ kinds: [7375], authors: [pubkey] }]);
|
||||||
|
|
||||||
|
const organizedProofs = await organizeProofs(unspentProofs, signer);
|
||||||
|
|
||||||
|
assertEquals(organizedProofs, {
|
||||||
|
'https://mint.soul.com': {
|
||||||
|
totalBalance: 100,
|
||||||
|
[event1.id]: { event: event1, balance: 100 },
|
||||||
|
},
|
||||||
|
'https://mint-fashion.com': {
|
||||||
|
totalBalance: 124,
|
||||||
|
[event2.id]: { event: event2, balance: 1 },
|
||||||
|
[event3.id]: { event: event3, balance: 123 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { z } from 'zod';
|
||||||
|
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '@/utils/log.ts';
|
||||||
import { isNostrId } from '@/utils.ts';
|
import { isNostrId } from '@/utils.ts';
|
||||||
|
import { tokenEventSchema } from '@/schemas/cashu.ts';
|
||||||
|
|
||||||
type Data = {
|
type Data = {
|
||||||
wallet: NostrEvent;
|
wallet: NostrEvent;
|
||||||
|
|
@ -99,4 +100,43 @@ async function validateAndParseWallet(
|
||||||
return { data: { wallet, nutzapInfo, privkey, p2pk, mints }, error: null };
|
return { data: { wallet, nutzapInfo, privkey, p2pk, mints }, error: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
export { validateAndParseWallet };
|
type OrganizedProofs = {
|
||||||
|
[mintUrl: string]: {
|
||||||
|
/** Total balance in this mint */
|
||||||
|
totalBalance: number;
|
||||||
|
/** Event id */
|
||||||
|
[eventId: string]: {
|
||||||
|
event: NostrEvent;
|
||||||
|
/** Total balance in this event */
|
||||||
|
balance: number;
|
||||||
|
} | number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
async function organizeProofs(
|
||||||
|
events: NostrEvent[],
|
||||||
|
signer: SetRequired<NostrSigner, 'nip44'>,
|
||||||
|
): Promise<OrganizedProofs> {
|
||||||
|
const organizedProofs: OrganizedProofs = {};
|
||||||
|
const pubkey = await signer.getPublicKey();
|
||||||
|
|
||||||
|
for (const event of events) {
|
||||||
|
const decryptedContent = await signer.nip44.decrypt(pubkey, event.content);
|
||||||
|
const { data: token, success } = n.json().pipe(tokenEventSchema).safeParse(decryptedContent);
|
||||||
|
if (!success) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const { mint, proofs } = token;
|
||||||
|
|
||||||
|
const balance = proofs.reduce((prev, current) => prev + current.amount, 0);
|
||||||
|
|
||||||
|
if (!organizedProofs[mint]) {
|
||||||
|
organizedProofs[mint] = { totalBalance: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
organizedProofs[mint] = { ...organizedProofs[mint], [event.id]: { event, balance } };
|
||||||
|
organizedProofs[mint].totalBalance += balance;
|
||||||
|
}
|
||||||
|
return organizedProofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { organizeProofs, validateAndParseWallet };
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue