Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions packages/targets/payment-coinpay/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@profullstack/sh1pt-target-payment-coinpay",
"version": "0.1.11",
"type": "module",
"main": "./src/index.ts",
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"prepublishOnly": "pnpm build"
},
"dependencies": {
"@profullstack/sh1pt-core": "workspace:*"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/profullstack/sh1pt.git",
"directory": "packages/targets/payment-coinpay"
},
"files": ["dist"],
"publishConfig": {
"access": "public",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
}
}
}
7 changes: 7 additions & 0 deletions packages/targets/payment-coinpay/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { contractTestTarget } from '@profullstack/sh1pt-core/testing';
import target from './index.js';

contractTestTarget(target, {
sampleConfig: { command: 'create', args: { amount: 100, blockchain: 'BTC' }, businessId: 'biz_test' },
requiredSecrets: ['COINPAY_API_KEY'],
});
104 changes: 104 additions & 0 deletions packages/targets/payment-coinpay/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { defineTarget, setupGuide, exec } from '@profullstack/sh1pt-core';

interface Config {
command?: 'create' | 'get' | 'list' | 'rates';
args?: Record<string, unknown>;
businessId?: string;
description?: string;
}

export default defineTarget<Config>({
id: 'payment-coinpay',
kind: 'payment',
label: 'CoinPay (CLI wrapper)',

async build(ctx, config) {
ctx.log('coinpay: verifying CLI availability');

// 1. Auto-install CLI if missing
try {
await exec('coinpay', ['--version'], { log: ctx.log, throwOnNonZero: false });
} catch {
ctx.log('CLI not found — installing globally');
await exec('npm', ['install', '-g', '@profullstack/coinpay'], {
log: ctx.log, throwOnNonZero: true,
});
}

// 2. Delegate API key setup to the wrapped CLI
try {
const { stdout } = await exec('coinpay', ['config', 'get-key'], {
log: ctx.log, throwOnNonZero: false,
});
if (!stdout.trim()) {
const key = ctx.secret('COINPAY_API_KEY');
if (key) {
await exec('coinpay', ['config', 'set-key', key], {
log: ctx.log, throwOnNonZero: true,
});
} else {
throw new Error('COINPAY_API_KEY not set. Run: sh1pt secret set COINPAY_API_KEY <key>');
}
}
} catch (e) {
throw new Error(`Config check failed: ${e instanceof Error ? e.message : String(e)}`);
}

return { artifact: 'ready' };
},

async ship(ctx, config) {
const cmd = config.command ?? 'create';
if (ctx.dryRun) return { id: 'dry-run', meta: { command: cmd } };

switch (cmd) {
case 'create': {
const args = ['payment', 'create'];
const bizId = config.businessId ?? (config.args?.businessId as string);
if (bizId) args.push('--business-id', bizId);
if (config.args?.amount) args.push('--amount', String(config.args.amount));
if (config.args?.blockchain) args.push('--blockchain', String(config.args.blockchain));
if (config.description) args.push('--description', config.description);

const { stdout } = await exec('coinpay', args, { log: ctx.log, throwOnNonZero: true });
return { id: `cp_${Date.now()}`, meta: { raw: stdout.trim() } };
}

case 'get': {
const paymentId = config.args?.paymentId as string;
if (!paymentId) throw new Error('paymentId required for get command');
const { stdout } = await exec('coinpay', ['payment', 'get', paymentId], { log: ctx.log });
return { id: paymentId, meta: { raw: stdout.trim() } };
}

case 'list': {
const args = ['payment', 'list'];
const bizId = config.businessId ?? (config.args?.businessId as string);
if (bizId) args.push('--business-id', bizId);
const { stdout } = await exec('coinpay', args, { log: ctx.log });
return { id: `list-${Date.now()}`, meta: { raw: stdout.trim() } };
}

case 'rates': {
const coin = (config.args?.coin as string) ?? 'BTC';
const fiat = (config.args?.fiat as string) ?? 'USD';
const { stdout } = await exec('coinpay', ['rates', 'get', coin, '--fiat', fiat], { log: ctx.log });
return { id: `${coin}-${fiat}`, meta: { raw: stdout.trim() } };
}

default:
throw new Error(`Unknown command: ${cmd}`);
}
},

setup: setupGuide({
label: 'CoinPay CLI',
vendorDocUrl: 'https://coinpayportal.com/docs/sdk#cli',
steps: [
'Install the CLI: npm install -g @profullstack/coinpay',
'Get API key from dashboard → API Keys',
'Run: coinpay config set-key <key>',
'Or: sh1pt secret set COINPAY_API_KEY <key>',
],
}),
});
5 changes: 5 additions & 0 deletions packages/targets/payment-coinpay/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": { "outDir": "./dist", "rootDir": "./src" },
"include": ["src"]
}