aboutsummaryrefslogtreecommitdiffstats
path: root/config.js.sample
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2014-08-08 11:43:22 -0700
committerAdam Soltys <[email protected]>2014-08-08 11:43:22 -0700
commitf08781b0b9507a52b76c5d2a56bb4358e880c550 (patch)
treeaf7e811c0db3834cf8b6bc8a5b0d8856f7561334 /config.js.sample
parent2cc86381a6f79cd729048b34a72b70562a7b0ace (diff)
downloadcoinos-server-f08781b0b9507a52b76c5d2a56bb4358e880c550.tar.gz
coinos-server-f08781b0b9507a52b76c5d2a56bb4358e880c550.zip
Config sample
Diffstat (limited to 'config.js.sample')
-rw-r--r--config.js.sample4
1 files changed, 4 insertions, 0 deletions
diff --git a/config.js.sample b/config.js.sample
new file mode 100644
index 00000000..3d2d7a5c
--- /dev/null
+++ b/config.js.sample
@@ -0,0 +1,4 @@
+(function() {
+ module.exports.secret = 'weareallmadeofstars';
+
+}).call(this);
font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #00D; font-weight: bold } /* Literal.Number */ .highlight .s { color: #D20; background-color: #FFF0F0 } /* Literal.String */ .highlight .na { color: #369 } /* Name.Attribute */ .highlight .nb { color: #038 } /* Name.Builtin */ .highlight .nc { color: #B06; font-weight: bold } /* Name.Class */ .highlight .no { color: #036; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555 } /* Name.Decorator */ .highlight .ne { color: #B06; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #06B; font-weight: bold } /* Name.Function */ .highlight .nl { color: #369; font-style: italic } /* Name.Label */ .highlight .nn { color: #B06; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #369; font-weight: bold } /* Name.Property */ .highlight .nt { color: #B06; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #369 } /* Name.Variable */ .highlight .ow { color: #080 } /* Operator.Word */ .highlight .w { color: #BBB } /* Text.Whitespace */ .highlight .mb { color: #00D; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #00D; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #00D; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #00D; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #00D; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #D20; background-color: #FFF0F0 } /* Literal.String.Affix */ .highlight .sb { color: #D20; background-color: #FFF0F0 } /* Literal.String.Backtick */ .highlight .sc { color: #D20; background-color: #FFF0F0 } /* Literal.String.Char */ .highlight .dl { color: #D20; background-color: #FFF0F0 } /* Literal.String.Delimiter */ .highlight .sd { color: #D20; background-color: #FFF0F0 } /* Literal.String.Doc */ .highlight .s2 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Double */ .highlight .se { color: #04D; background-color: #FFF0F0 } /* Literal.String.Escape */ .highlight .sh { color: #D20; background-color: #FFF0F0 } /* Literal.String.Heredoc */ .highlight .si { color: #33B; background-color: #FFF0F0 } /* Literal.String.Interpol */ .highlight .sx { color: #2B2; background-color: #F0FFF0 } /* Literal.String.Other */ .highlight .sr { color: #080; background-color: #FFF0FF } /* Literal.String.Regex */ .highlight .s1 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Single */ .highlight .ss { color: #A60; background-color: #FFF0F0 } /* Literal.String.Symbol */ .highlight .bp { color: #038 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #06B; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #369 } /* Name.Variable.Class */ .highlight .vg { color: #D70 } /* Name.Variable.Global */ .highlight .vi { color: #33B } /* Name.Variable.Instance */ .highlight .vm { color: #369 } /* Name.Variable.Magic */ .highlight .il { color: #00D; font-weight: bold } /* Literal.Number.Integer.Long */
// CLINK offer codes + the offer service: TLV roundtrip, and a full
// kind-21001 request/response through the nwc feature with a fake transport.
// Run: bun tools/noffer-test.js
import { hex } from '@scure/base';
import * as nip44 from 'nostr-tools/nip44';
import { finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools/pure';
import { encodeNoffer, decodeNoffer } from '../src/noffer.js';
import { nwcFeature } from '../src/features/nwc.js';

let fails = 0;
const check = (name, ok, detail = '') => {
  console.log(` ${ok ? '✓' : '✗'} ${name}${detail ? ' — ' + String(detail).slice(0, 120) : ''}`);
  if (!ok) fails++;
};

console.log('[offer code TLV]');
const pk = getPublicKey(generateSecretKey());
const code = encodeNoffer({ pubkey: pk, relay: 'wss://relay.coinos.io', offerId: 'zap_default', priceType: 2 });
check('encodes to noffer1…', code.startsWith('noffer1'), code.slice(0, 24));
const dec = decodeNoffer(code);
check('pubkey roundtrips', dec.pubkey === pk);
check('relay roundtrips', dec.relay === 'wss://relay.coinos.io');
check('offer id roundtrips', dec.offerId === 'zap_default');
check('price type roundtrips', dec.priceType === 2);

console.log('\n[offer service]');
// harness mirroring tools/nwc-test.js
const store = {};
let subHandlers = []; // every listen() subscription callback
const published = [];
const nwcTransport = {
  subscribe: (relays, filter, on) => { subHandlers.push({ filter, on }); return () => {}; },
  publish: async (relays, evt) => { published.push(evt); return true; },
  query: async () => [],
};
const wallet = {
  watchOnly: false,
  loadFeatureState: (n, fb) => JSON.parse(store['fs:' + n] || 'null') || fb,
  saveFeatureState: (n, st) => { store['fs:' + n] = JSON.stringify(st); },
  _cacheKey: () => 'w1',
  account: () => null,
  saveCache: () => {},
  registerCacheExtension: () => {},
};
const hooks = {
  arkReady: () => true,
  arkMakeInvoice: async (sat, desc) => ({ invoice: 'lnbc_mock_' + sat, paymentHash: 'cd'.repeat(32), amountSat: sat }),
  arkMovements: () => [],
  arkBgWrite: async () => {},
  arkBgSpendableSat: async () => 0,
};
const ctx = {
  h: () => null, ui: {}, render: () => {}, wallet,
  hook: (n, ...a) => (hooks[n] ? hooks[n](...a) : null),
  fmtAmount: String, unitLabel: () => 'sats', copyBtn: () => null, toast: () => {}, nwcTransport,
};
const f = nwcFeature(ctx);
f.init();
await new Promise((r) => setTimeout(r, 50));

const offerCode = f.nwcOfferString();
check('feature mints an offer code', !!offerCode && offerCode.startsWith('noffer1'), (offerCode || '').slice(0, 24));
const offer = decodeNoffer(offerCode);
const offerSub = subHandlers.find((s2) => (s2.filter.kinds || []).includes(21001));
check('subscribed for offer requests', !!offerSub && offerSub.filter['#p'][0] === offer.pubkey);

// a payer requests 21 sats with a zap attached
const payerSk = generateSecretKey();
const zapReq = finalizeEvent({ kind: 9734, created_at: Math.floor(Date.now() / 1000),
  tags: [['p', 'ab'.repeat(32)], ['relays', 'wss://relay.damus.io']], content: '' }, payerSk);
const reqPayload = { offer: 'zap_default', amount_sats: 21, zap: JSON.stringify(zapReq) };
const convKey = nip44.getConversationKey(payerSk, offer.pubkey);
const reqEv = finalizeEvent({
  kind: 21001, created_at: Math.floor(Date.now() / 1000),
  tags: [['p', offer.pubkey], ['clink_version', '1']],
  content: nip44.encrypt(JSON.stringify(reqPayload), convKey),
}, payerSk);
await offerSub.on(reqEv);
await new Promise((r) => setTimeout(r, 100));

const resp = published.find((e) => e.kind === 21001);
check('offer request answered', !!resp);
if (resp) {
  const body = JSON.parse(nip44.decrypt(resp.content, convKey));
  check('response carries the invoice', body.bolt11 === 'lnbc_mock_21', JSON.stringify(body));
  check('response e-tags the request', resp.tags.some((t) => t[0] === 'e' && t[1] === reqEv.id));
  check('response signed by the offer key', resp.pubkey === offer.pubkey);
}
const st = JSON.parse(store['fs:nwc']);
check('zap held for its receipt', (st.zapPending || []).length === 1 && st.zapPending[0].invoice === 'lnbc_mock_21');

// replay: same event must not be answered twice
const before = published.filter((e) => e.kind === 21001).length;
await offerSub.on(reqEv);
await new Promise((r) => setTimeout(r, 60));
check('replayed request ignored', published.filter((e) => e.kind === 21001).length === before);

console.log(fails ? `\n❌ ${fails} failure(s)` : '\n✅ offer service behaves');
process.exit(fails ? 1 : 0);