style: run prettier --write src

This commit is contained in:
Tim Man
2023-07-11 14:23:09 +08:00
parent 26d1801ce9
commit 404f7683b2
11 changed files with 89 additions and 129 deletions

View File

@@ -6,7 +6,7 @@
"quoteProps": "as-needed",
"singleQuote": true,
"semi": true,
"printWidth": 100,
"printWidth": 120,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all"

View File

@@ -1,29 +1,23 @@
import { NextFunction, Request, Response } from "express";
import {
import { NextFunction, Request, Response } from 'express';
import {
deserializeTransaction,
sponsorTransaction,
broadcastTransaction,
SponsoredAuthorization
} from "@stacks/transactions";
import { bytesToHex } from "@stacks/common";
SponsoredAuthorization,
} from '@stacks/transactions';
import { bytesToHex } from '@stacks/common';
import { StacksMainnet } from '@stacks/network';
import envVariables from '../../../config/config';
import {
SponsorAccountsKey,
} from '../../constants'
import {
import { SponsorAccountsKey } from '../../constants';
import {
lockRandomSponsorAccount,
getAccountNonce,
incrementAccountNonce,
unlockSponsorAccount,
check
check,
} from '../../nonce';
import {
getAccountAddress
} from '../../utils';
import {
validateTransaction
} from '../../validation';
import { getAccountAddress } from '../../utils';
import { validateTransaction } from '../../validation';
let cache = require('../../cache');
@@ -32,14 +26,14 @@ export class Controller {
try {
const accounts = cache.instance().get(SponsorAccountsKey);
const addresses = [];
accounts.forEach(account => {
accounts.forEach((account) => {
const address = getAccountAddress(account);
addresses.push(address);
});
return res.json({
active: true,
sponsor_addresses: addresses
active: true,
sponsor_addresses: addresses,
});
} catch (error) {
next(error);
@@ -56,7 +50,7 @@ export class Controller {
if (!validTx) {
throw new Error('Transaction not valid for sponsorship');
}
}
// attempt to lock a random sponsor account from wallet
const account = await lockRandomSponsorAccount();
@@ -72,7 +66,7 @@ export class Controller {
transaction: tx,
sponsorPrivateKey: account.stxPrivateKey,
network,
sponsorNonce: nonce
sponsorNonce: nonce,
});
// make sure fee doesn't exceed maximum
@@ -93,7 +87,7 @@ export class Controller {
incrementAccountNonce(account);
}
return res.json({txid: result.txid, rawTx: bytesToHex(signedTx.serialize())});
return res.json({ txid: result.txid, rawTx: bytesToHex(signedTx.serialize()) });
} finally {
unlockSponsorAccount(account);
}

View File

@@ -1,10 +1,10 @@
import { Controller } from "./controller";
import { Controller } from './controller';
const express = require("express");
const express = require('express');
const router = express.Router();
const controller = new Controller();
router.get("/info", controller.info);
router.post("/sponsor", controller.sponsor);
router.get('/info', controller.info);
router.post('/sponsor', controller.sponsor);
export = router;

View File

@@ -1,12 +1,12 @@
let nodeCache = require('node-cache')
let cache = null
let nodeCache = require('node-cache');
let cache = null;
exports.start = function (done) {
if (cache) return done()
if (cache) return done();
cache = new nodeCache()
}
cache = new nodeCache();
};
exports.instance = function () {
return cache
}
return cache;
};

View File

@@ -1,4 +1,4 @@
export const SponsorAccountsKey = "SponsorAccounts";
export const AddressNoncePrefix = "Nonce-";
export const AddressLockPrefix = "Lock-";
export const MaxLockAttempts = 10;
export const SponsorAccountsKey = 'SponsorAccounts';
export const AddressNoncePrefix = 'Nonce-';
export const AddressLockPrefix = 'Lock-';
export const MaxLockAttempts = 10;

View File

@@ -1,23 +1,23 @@
import { json } from 'body-parser';
import { errorHandler, wrongRouteHandler } from "./response";
import { errorHandler, wrongRouteHandler } from './response';
import { initializeSponsorWallet } from './initialization';
let cache = require('./cache')
let cache = require('./cache');
const express = require("express");
var cors = require('cors')
const express = require('express');
var cors = require('cors');
const app = express();
const v1 = require("./api/v1/router");
const v1 = require('./api/v1/router');
let port = 8080;
if (app.get("env") === "development") {
if (app.get('env') === 'development') {
port = 3100;
}
cache.start(function (err) {
if (err) console.error(err)
})
if (err) console.error(err);
});
// initialize the sponsor wallets to the correct nonce
initializeSponsorWallet();
@@ -26,18 +26,18 @@ app.use(json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Ok')
res.send('Ok');
});
app.use("/v1", v1);
app.use('/v1', v1);
app.use(errorHandler);
app.use(wrongRouteHandler);
const server = app.listen(port, () => {
console.log(
`Stacks Transaction Sponsor Web Service started and listening at http://localhost:${port} in ${app.get(
"env"
)} mode`
'env',
)} mode`,
);
});

View File

@@ -1,20 +1,11 @@
import { StacksMainnet } from "@stacks/network";
import {
getAddressFromPrivateKey,
TransactionVersion
} from "@stacks/transactions";
import envVariables from "../config/config";
import axios from "axios";
import {
generateWallet,
generateNewAccount
} from "@stacks/wallet-sdk";
import {
SponsorAccountsKey,
AddressNoncePrefix
} from './constants'
import { StacksMainnet } from '@stacks/network';
import { getAddressFromPrivateKey, TransactionVersion } from '@stacks/transactions';
import envVariables from '../config/config';
import axios from 'axios';
import { generateWallet, generateNewAccount } from '@stacks/wallet-sdk';
import { SponsorAccountsKey, AddressNoncePrefix } from './constants';
let cache = require('./cache')
let cache = require('./cache');
export interface StxAddressDataResponse {
balance: string;
@@ -23,7 +14,7 @@ export interface StxAddressDataResponse {
nonce: number;
}
export async function initializeSponsorWallet() {
export async function initializeSponsorWallet() {
const seed = envVariables.seed;
const password = envVariables.password;
const numAddresses = Number(envVariables.numAddresses);
@@ -36,18 +27,18 @@ export async function initializeSponsorWallet() {
// derive specified number of accounts/addresses
for (let i = 0; i < numAddresses - 1; i++) {
const newAccounts = await generateNewAccount(wallet);
const newAccounts = await generateNewAccount(wallet);
wallet.accounts = newAccounts.accounts;
}
// cache sponsor accounts
const result = cache.instance().set(SponsorAccountsKey, wallet.accounts);
// get the correct next nonce for each addresses
wallet.accounts.forEach(account => {
wallet.accounts.forEach((account) => {
const address = getAddressFromPrivateKey(account.stxPrivateKey, TransactionVersion.Mainnet);
setupAccountNonce(address);
});
});
}
export async function setupAccountNonce(address: string) {
@@ -68,12 +59,10 @@ export async function setupAccountNonce(address: string) {
const nextNonce = nonce + pendingTransactionCount;
// cache correct next nonce
const result = cache.instance().set(AddressNoncePrefix+address, nextNonce);
const result = cache.instance().set(AddressNoncePrefix + address, nextNonce);
}
export async function getMempoolTransactions(
stxAddress: string
): Promise<number> {
export async function getMempoolTransactions(stxAddress: string): Promise<number> {
const network = new StacksMainnet();
let apiUrl = `${network.coreApiUrl}/extended/v1/tx/mempool?address=${stxAddress}`;
@@ -88,4 +77,4 @@ export async function getMempoolTransactions(
.then((response) => {
return response.data.total;
});
}
}

View File

@@ -1,24 +1,15 @@
import {
SponsorAccountsKey,
AddressNoncePrefix,
AddressLockPrefix,
MaxLockAttempts
} from './constants'
import { SponsorAccountsKey, AddressNoncePrefix, AddressLockPrefix, MaxLockAttempts } from './constants';
import { Account } from '@stacks/wallet-sdk';
import envVariables from "../config/config";
import envVariables from '../config/config';
import {
sleep,
getRandomInt,
getAccountAddress
} from './utils';
import { sleep, getRandomInt, getAccountAddress } from './utils';
let cache = require('./cache');
export function check(address: string): boolean {
return cache.instance().get(AddressLockPrefix+address);
return cache.instance().get(AddressLockPrefix + address);
}
// lock address nonce
@@ -27,14 +18,14 @@ export function lock(address: string): boolean {
if (lock === true) {
return false;
} else {
cache.instance().set(AddressLockPrefix+address, true);
cache.instance().set(AddressLockPrefix + address, true);
return true;
}
}
// unlock address nonce
export function unlock(address: string) {
cache.instance().set(AddressLockPrefix+address, false);
cache.instance().set(AddressLockPrefix + address, false);
}
export function getRandomSponsorAccount(): Account {
@@ -50,7 +41,7 @@ export async function lockRandomSponsorAccount(): Promise<Account> {
var locked = false;
var attempts = 0;
while(!locked) {
while (!locked) {
const account = getRandomSponsorAccount();
const address = getAccountAddress(account);
locked = lock(address);
@@ -73,12 +64,12 @@ export function unlockSponsorAccount(account: Account) {
export function getAccountNonce(account: Account) {
const address = getAccountAddress(account);
const nonce = cache.instance().get(AddressNoncePrefix+address);
const nonce = cache.instance().get(AddressNoncePrefix + address);
return nonce;
}
export function incrementAccountNonce(account: Account) {
const address = getAccountAddress(account);
const currentNonce = getAccountNonce(account);
return cache.instance().set(AddressNoncePrefix+address, currentNonce + 1);
return cache.instance().set(AddressNoncePrefix + address, currentNonce + 1);
}

View File

@@ -1,15 +1,15 @@
export function errorHandler(err, req, res, next) {
err.statusCode = err.statusCode || 400;
res.status(err.statusCode).json({
status: err.statusCode,
message: err.message
})
err.statusCode = err.statusCode || 400;
res.status(err.statusCode).json({
status: err.statusCode,
message: err.message,
});
}
export function wrongRouteHandler(req, res, next) {
const statusCode = 404;
res.status(statusCode).json({
status: statusCode,
message: "Route not found. Request failed with status code 404 "
})
}
const statusCode = 404;
res.status(statusCode).json({
status: statusCode,
message: 'Route not found. Request failed with status code 404 ',
});
}

View File

@@ -1,8 +1,5 @@
import { Account } from '@stacks/wallet-sdk';
import {
getAddressFromPrivateKey,
TransactionVersion
} from "@stacks/transactions";
import { getAddressFromPrivateKey, TransactionVersion } from '@stacks/transactions';
export function getRandomInt(min, max) {
min = Math.ceil(min);
@@ -16,9 +13,6 @@ export function sleep(ms) {
});
}
export function getAccountAddress(
account: Account,
version: TransactionVersion = TransactionVersion.Mainnet
): string {
export function getAccountAddress(account: Account, version: TransactionVersion = TransactionVersion.Mainnet): string {
return getAddressFromPrivateKey(account.stxPrivateKey, version);
}
}

View File

@@ -1,43 +1,35 @@
import {
PayloadType,
ContractCallPayload,
getAbi,
addressToString,
StacksTransaction
} from "@stacks/transactions";
import { PayloadType, ContractCallPayload, getAbi, addressToString, StacksTransaction } from '@stacks/transactions';
// rules for transaction sponsorship eligibility
// customize this if you are forking this repo
export async function validateTransaction(transaction: StacksTransaction) {
if (transaction.payload.payloadType !== PayloadType.ContractCall) {
throw new Error('Transaction is not a contract call');
}
}
const payload = transaction.payload as ContractCallPayload;
// check and limit to SIP-09 transfers calls
if (payload.functionName.content.toString() !== 'transfer') {
throw new Error('Transaction is not a NFT transfer contract call');
}
}
const contractAddress = addressToString(payload.contractAddress);
const contractName = payload.contractName.content.toString();
const functionName = payload.functionName.content.toString();
const abi = await getAbi(contractAddress, contractName, "mainnet");
const abi = await getAbi(contractAddress, contractName, 'mainnet');
const func = abi.functions.find((func) => {
return func.name === functionName;
})
});
if (func.args.length !== 3) {
throw new Error('Transaction is not a NFT transfer contract call');
}
// check against sip-09 interface for transfer
if (func.args[0].type !== 'uint128'
|| func.args[1].type !== 'principal'
|| func.args[2].type !== 'principal') {
if (func.args[0].type !== 'uint128' || func.args[1].type !== 'principal' || func.args[2].type !== 'principal') {
throw new Error('Transaction is not a NFT transfer contract call');
}
return true;
}
}