You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wallet-generation.js 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. "use strict";
  2. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  3. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  4. return new (P || (P = Promise))(function (resolve, reject) {
  5. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  6. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  7. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  8. step((generator = generator.apply(thisArg, _arguments || [])).next());
  9. });
  10. };
  11. Object.defineProperty(exports, "__esModule", { value: true });
  12. exports.getFaucetUrl = exports.FaucetNetwork = void 0;
  13. const https = require("https");
  14. const common_1 = require("../common");
  15. const schema_validator_1 = require("../common/schema-validator");
  16. const errors_1 = require("../common/errors");
  17. var FaucetNetwork;
  18. (function (FaucetNetwork) {
  19. FaucetNetwork["Testnet"] = "faucet.altnet.rippletest.net";
  20. FaucetNetwork["Devnet"] = "faucet.devnet.rippletest.net";
  21. })(FaucetNetwork = exports.FaucetNetwork || (exports.FaucetNetwork = {}));
  22. const INTERVAL_SECONDS = 1;
  23. const MAX_ATTEMPTS = 20;
  24. function generateFaucetWallet(address) {
  25. return __awaiter(this, void 0, void 0, function* () {
  26. if (!this.isConnected())
  27. throw new errors_1.RippledError("RippleAPI not connected, cannot call faucet");
  28. let body;
  29. let startingBalance = 0;
  30. let faucetUrl = getFaucetUrl(this);
  31. if (address && schema_validator_1.isValidAddress(address)) {
  32. body = new TextEncoder().encode(JSON.stringify({
  33. destination: address
  34. }));
  35. const addressToFundBalance = yield getAddressXrpBalance(this, address);
  36. if (addressToFundBalance && !isNaN(+addressToFundBalance)) {
  37. startingBalance = +addressToFundBalance;
  38. }
  39. else {
  40. startingBalance = 0;
  41. }
  42. }
  43. const options = {
  44. hostname: faucetUrl,
  45. port: 443,
  46. path: '/accounts',
  47. method: 'POST',
  48. headers: {
  49. 'Content-Type': 'application/json',
  50. 'Content-Length': body ? body.length : 0
  51. }
  52. };
  53. return new Promise((resolve, reject) => {
  54. const request = https.request(options, (response) => {
  55. const chunks = [];
  56. response.on('data', (d) => {
  57. chunks.push(d);
  58. });
  59. response.on('end', () => __awaiter(this, void 0, void 0, function* () {
  60. const body = Buffer.concat(chunks).toString();
  61. if (response.headers['content-type'].startsWith('application/json')) {
  62. const wallet = JSON.parse(body);
  63. const classicAddress = wallet.account.classicAddress;
  64. if (classicAddress) {
  65. try {
  66. const isFunded = yield hasAddressBalanceIncreased(this, classicAddress, startingBalance);
  67. if (isFunded) {
  68. resolve(wallet);
  69. }
  70. else {
  71. reject(new common_1.errors.XRPLFaucetError(`Unable to fund address with faucet after waiting ${INTERVAL_SECONDS * MAX_ATTEMPTS} seconds`));
  72. }
  73. }
  74. catch (err) {
  75. reject(new common_1.errors.XRPLFaucetError(err));
  76. }
  77. }
  78. else {
  79. reject(new common_1.errors.XRPLFaucetError(`The faucet account classic address is undefined`));
  80. }
  81. }
  82. else {
  83. reject({
  84. statusCode: response.statusCode,
  85. contentType: response.headers['content-type'],
  86. body
  87. });
  88. }
  89. }));
  90. });
  91. request.write(body ? body : '');
  92. request.on('error', (error) => {
  93. reject(error);
  94. });
  95. request.end();
  96. });
  97. });
  98. }
  99. function getAddressXrpBalance(api, address) {
  100. return __awaiter(this, void 0, void 0, function* () {
  101. try {
  102. const balances = yield api.getBalances(address);
  103. const xrpBalance = balances.filter((balance) => balance.currency.toUpperCase() === 'XRP');
  104. return xrpBalance[0].value;
  105. }
  106. catch (err) {
  107. return `Unable to retrieve ${address} balance. Error: ${err}`;
  108. }
  109. });
  110. }
  111. function hasAddressBalanceIncreased(api, address, originalBalance) {
  112. return __awaiter(this, void 0, void 0, function* () {
  113. return new Promise((resolve, reject) => {
  114. let attempts = MAX_ATTEMPTS;
  115. const interval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
  116. if (attempts < 0) {
  117. clearInterval(interval);
  118. resolve(false);
  119. }
  120. else {
  121. attempts--;
  122. }
  123. try {
  124. const newBalance = +(yield getAddressXrpBalance(api, address));
  125. if (newBalance > originalBalance) {
  126. clearInterval(interval);
  127. resolve(true);
  128. }
  129. }
  130. catch (err) {
  131. clearInterval(interval);
  132. reject(new common_1.errors.XRPLFaucetError(`Unable to check if the address ${address} balance has increased. Error: ${err}`));
  133. }
  134. }), INTERVAL_SECONDS * 1000);
  135. });
  136. });
  137. }
  138. function getFaucetUrl(api) {
  139. const connectionUrl = api.connection.getUrl();
  140. if (connectionUrl.includes('altnet') || connectionUrl.includes('testnet')) {
  141. return FaucetNetwork.Testnet;
  142. }
  143. if (connectionUrl.includes('devnet')) {
  144. return FaucetNetwork.Devnet;
  145. }
  146. return undefined;
  147. }
  148. exports.getFaucetUrl = getFaucetUrl;
  149. exports.default = generateFaucetWallet;
  150. //# sourceMappingURL=wallet-generation.js.map