-
Notifications
You must be signed in to change notification settings - Fork 163
Expand file tree
/
Copy pathalbedo-wallet.ts
More file actions
168 lines (137 loc) · 5.68 KB
/
Copy pathalbedo-wallet.ts
File metadata and controls
168 lines (137 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/**
* albedo-wallet.ts — Demonstrates Albedo wallet integration
*
* Albedo is a web-based wallet that doesn't require browser extensions.
* It opens a popup window for user authentication and transaction signing.
*
* Required env vars:
* TIKKA_NETWORK testnet | mainnet | standalone (default: testnet)
* TIKKA_RAFFLE_ID Numeric raffle ID to buy into
*
* Optional env vars:
* TIKKA_QUANTITY Number of tickets to buy (default: 1)
*
* Usage:
* TIKKA_NETWORK=testnet TIKKA_RAFFLE_ID=1 \
* npx ts-node examples/albedo-wallet.ts
*
* Note: This example requires a browser environment to work properly.
* Albedo will open a popup window for user interaction.
*/
import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { AppModule } from '../src/app.module';
import { RaffleService } from '../src/modules/raffle/raffle.service';
import { TicketService } from '../src/modules/ticket/ticket.service';
import { AlbedoAdapter } from '../src/wallet/albedo.adapter';
import { TikkaNetwork } from '../src/network/network.config';
import { RaffleStatus } from '../src/contract/bindings';
import { Networks } from '@stellar/stellar-sdk';
async function main() {
const network = (process.env.TIKKA_NETWORK ?? 'testnet') as TikkaNetwork;
const raffleId = parseInt(process.env.TIKKA_RAFFLE_ID ?? '0', 10);
const quantity = parseInt(process.env.TIKKA_QUANTITY ?? '1', 10);
if (!raffleId) {
console.error('Error: TIKKA_RAFFLE_ID is required');
process.exit(1);
}
// Get network passphrase
const networkPassphrase = network === 'mainnet'
? Networks.PUBLIC
: Networks.TESTNET;
console.log('🌐 Initializing Albedo wallet adapter...');
console.log(` Network: ${network}`);
console.log(` Passphrase: ${networkPassphrase}\n`);
// Create Albedo adapter
const wallet = new AlbedoAdapter({ networkPassphrase });
// Check if Albedo is available
if (!wallet.isAvailable()) {
console.error('❌ Albedo is not available in this environment');
console.error(' Albedo requires a browser environment with DOM support');
process.exit(1);
}
console.log('✅ Albedo is available\n');
// Initialize SDK
const app = await NestFactory.createApplicationContext(
AppModule.forRoot({ network, wallet }),
{ logger: false },
);
const raffleService = app.get(RaffleService);
const ticketService = app.get(TicketService);
try {
// Step 1: Request public key from Albedo
console.log('📋 Step 1: Requesting public key from Albedo...');
console.log(' (A popup window will open for authentication)');
const publicKey = await wallet.getPublicKey();
console.log(`✅ Public key obtained: ${publicKey}\n`);
// Step 2: Verify raffle is open
console.log('📋 Step 2: Verifying raffle status...');
const raffleRes = await raffleService.get(raffleId);
if (!raffleRes.success || !raffleRes.value) {
console.error(`❌ Failed to fetch raffle ${raffleId}: ${raffleRes.error}`);
await app.close();
process.exit(1);
}
const raffle = raffleRes.value;
if (raffle.status !== RaffleStatus.Open) {
console.error(`❌ Raffle ${raffleId} is not open (status=${raffle.status})`);
await app.close();
process.exit(1);
}
const available = raffle.maxTickets - raffle.ticketsSold;
console.log(`✅ Raffle ${raffleId}:`);
console.log(` Status: Open`);
console.log(` Available tickets: ${available}`);
console.log(` Price: ${raffle.ticketPrice} XLM each\n`);
if (quantity > available) {
console.error(`❌ Requested ${quantity} tickets but only ${available} available`);
await app.close();
process.exit(1);
}
// Step 3: Buy tickets
console.log(`📋 Step 3: Purchasing ${quantity} ticket(s)...`);
console.log(' (Albedo popup will open for transaction signing)');
const result = await ticketService.buy({ raffleId, quantity });
if (!result.success) {
console.error(`\n❌ Purchase failed: ${result.error}`);
await app.close();
process.exit(1);
}
console.log('\n✅ Tickets purchased successfully!');
console.log(` Ticket IDs: ${(result.value?.ticketIds ?? []).join(', ')}`);
console.log(` Transaction: ${result.transactionHash}`);
console.log(` Ledger: ${result.ledger}\n`);
// Step 4: Verify tickets
console.log('📋 Step 4: Verifying your tickets...');
const myTicketsRes = await ticketService.getUserTickets({
raffleId,
userAddress: publicKey
});
console.log(`✅ All your tickets for raffle ${raffleId}:`);
console.log(` [${(myTicketsRes.value ?? []).join(', ')}]\n`);
// Optional: Demonstrate message signing
console.log('📋 Bonus: Demonstrating message signing...');
console.log(' (Albedo popup will open for message signing)');
const message = `Sign in to Tikka - ${new Date().toISOString()}`;
const signature = await wallet.signMessage(message);
console.log('✅ Message signed successfully!');
console.log(` Message: ${message}`);
console.log(` Signature: ${signature.substring(0, 32)}...\n`);
} catch (err: any) {
console.error('\n❌ Error:', err.message);
if (err.code === 'UserRejected') {
console.error(' User cancelled the Albedo request');
} else if (err.code === 'WalletNotInstalled') {
console.error(' @albedo-link/intent package is not installed');
console.error(' Run: npm install @albedo-link/intent');
}
await app.close();
process.exit(1);
}
await app.close();
console.log('✨ Example completed successfully!');
}
main().catch((err) => {
console.error('Fatal error:', err);
process.exit(1);
});