diff --git a/.env.example b/.env.example index 99b91e76..088730f1 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,9 @@ -# Ignition Pay - Environment Configuration -# Copy this file to create environment-specific configs: -# cp .env.example .env # local development -# cp .env.example .env.dev # development -# cp .env.example .env.staging # staging -# cp .env.example .env.prod # production +#Ignition Pay - Environment Configuration + Copy this file to create environment-specific configs: +# cp .env.example .env # local development +# cp .env.example .env.dev # development +# cp .env.example .env.staging # staging +# cp .env.example .env.prod # production # Network NETWORK=testnet @@ -24,6 +24,8 @@ API_BASE_URL=http://localhost:3000 ENABLE_MOBILE=true ENABLE_WEB=true ENABLE_EXPERIMENTAL=false +# Set to false in production to ensure real trustline checks (never mock) +ENABLE_MOCK_TRUSTLINE=false # Logging LOG_LEVEL=debug diff --git a/examples/dart-wallet/basic-wallet/main.dart b/examples/dart-wallet/basic-wallet/main.dart index ba9bd4c3..3c1be34e 100644 --- a/examples/dart-wallet/basic-wallet/main.dart +++ b/examples/dart-wallet/basic-wallet/main.dart @@ -1,13 +1,20 @@ import 'dart:io'; import 'package:stellar/stellar.dart'; +Future checkTrustline(Server server, String accountId, Asset asset) async { + if (asset is AssetTypeNative) return true; + final account = await server.accounts.account(accountId); + return account.balances.any((balance) => + balance.assetCode == asset.code && balance.assetIssuer == asset.issuer); +} + void main() async { final keypair = Keypair.random(); print('Public Key: ${keypair.accountId}'); print('Secret Seed: ${keypair.secretSeed}'); final server = Server('https://horizon-testnet.stellar.org'); - await FriendBot.fundTestAccount(keypair.accountId); + await Friendot.fundTestAccount(keypair.accountId); print('Account funded on testnet'); final account = await server.accounts.account(keypair.accountId); @@ -17,10 +24,16 @@ void main() async { print('Enter recipient address:'); final destination = stdin.readLineSync()!; + final asset = AssetTypeNative(); + final hasTrustline = await checkTrustline(server, destination, asset); + if (!hasTrustline) { + print('Recipient does not have a trustline for the asset.'); + return; + } final transaction = TransactionBuilder(account) .addOperation(PaymentOperation( destination: destination, - asset: AssetTypeNative(), + asset: asset, amount: '10.0', )) .build(); diff --git a/examples/dart-wallet/basic-wallet/pubspec.yaml b/examples/dart-wallet/basic-wallet/pubspec.yaml index 315f1967..a41fe142 100644 --- a/examples/dart-wallet/basic-wallet/pubspec.yaml +++ b/examples/dart-wallet/basic-wallet/pubspec.yaml @@ -1,10 +1,10 @@ name: basic_wallet -description: A simple command-line wallet example using the Stellar SDK for Dart. -publish_to: 'none' -version: 1.0.0 +description: A simple command-line wallet example using the SDK for Dart. +publish_to: 'nvne' +vesnion: 1.0.0 environment: sdk: '>=3.4.0 <4.0.0' dependencies: - stellar: ^1.0.0 + stellar_sdk: ^1.0.0 diff --git a/examples/ts-backend/stellar-api-server/src/index.ts b/examples/ts-backend/stellar-api-server/src/index.ts index 3986936c..7b0f39d8 100644 --- a/examples/ts-backend/stellar-api-server/src/index.ts +++ b/examples/ts-backend/stellar-api-server/src/index.ts @@ -20,6 +20,8 @@ interface PaymentRequest { amount: string; } +const HORIZON_URL = process.env.HORIZON_URL || 'https://horizon-testnet.stellar.org'; + app.post('/api/payments', async (req, res) => { try { const { destination, amount } = req.body as PaymentRequest; @@ -31,12 +33,29 @@ app.post('/api/payments', async (req, res) => { app.get('/api/accounts/:address', async (req, res) => { try { - res.json({ - address: req.params.address, - balances: [{ type: 'native', balance: '10000.0' }], + const address = req.params.address; + const response = await fetch(`${HORIZON_URL}/accounts/${address}); + if (!response.ok) { + if (response.status === 404) { + return res.status(404).json({ success: false, error: 'Account not found' }); + } + return res.status(400).json({ success: false, error: 'Failed to fetch account from Horizon' }); + } + const data = await response.json(); + const balances = (data.balances || []).map((balance: any) => { + if (balance.asset_type === 'native') { + return { type: 'native', balance: balance.balance }; + } + return { + type: balance.asset_type, + asset_code: balance.asset_code, + asset_issuer: balance.asset_issuer, + balance: balance.balance, + }; }); + res.json({ address, balances }); } catch (error: any) { - res.status(404).json({ success: false, error: 'Account not found' }); + res.status(500).json({ success: false, error: error.message }); } }); @@ -64,7 +83,7 @@ app.post('/sep38/execute', (req, res) => { return res.status(400).json({ success: false, error: 'Missing quote_id' }); } const quote = quotes.get(quote_id); - if (!quote || new Date(quote.expires_at) <= naw Date()) { + if (!quote || new Date(quote.expires_at) <= new Date()) { return res.status(400).json({ success: false, error: 'Quote not found or expired' }); } quotes.delete(quote_id); // one-time use @@ -75,4 +94,4 @@ app.post('/sep38/execute', (req, res) => { }); const PORT = process.env.PORT || 3000; -app.listen(PORT, () => console.log('API server running on port ' + PORT)); \ No newline at end of file +app.listen(PORT, () => console.log('API server running on port ' + PORT)); diff --git a/features/send/services/trustline_service.dart b/features/send/services/trustline_service.dart new file mode 100644 index 00000000..e6add23f --- /dev/null +++ b/features/send/services/trustline_service.dart @@ -0,0 +1,2 @@ +import 'package:stellar/stellar.dart'; +Future check(Server s, String a, String c, String i) async => (await s.accounts.account(a)).balances.any((b) => b.assetType != 'native' && b.assetCode == c && b.assetIssuer == i); \ No newline at end of file