Skip to content

Commit

Permalink
feat: remove payment info from manifest
Browse files Browse the repository at this point in the history
payment is set at a host/cluster level now
  • Loading branch information
blakebyrnes committed Sep 25, 2024
1 parent 0f43842 commit b4a9ad5
Show file tree
Hide file tree
Showing 58 changed files with 638 additions and 309 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
env:
GITHUB_URL: https://github.com/${{ github.repository }}
ADD_CHROME_VERSION: 120
ADD_CHROME_VERSION: 127
IMAGE: ulixee/ulixee-cloud

steps:
Expand Down
2 changes: 1 addition & 1 deletion client/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"dependencies": {
"@ulixee/commons": "2.0.0-alpha.29",
"@ulixee/datastore": "2.0.0-alpha.29",
"@argonprotocol/localchain": "0.0.6",
"@argonprotocol/localchain": "0.0.8",
"@ulixee/net": "2.0.0-alpha.29",
"@ulixee/schema": "2.0.0-alpha.29"
},
Expand Down
124 changes: 113 additions & 11 deletions cloud/main/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { applyEnvironmentVariables, parseEnvBool } from '@ulixee/commons/lib/envUtils';
import { filterUndefined } from '@ulixee/commons/lib/objectUtils';
import { parseIdentities } from '@ulixee/datastore-core/env';
import { parseAddress, parseIdentities } from '@ulixee/datastore-core/env';
import type ILocalchainConfig from '@ulixee/datastore/interfaces/ILocalchainConfig';
import { Command } from 'commander';
import * as Path from 'path';
import CloudNodeEnv from '../env';
Expand Down Expand Up @@ -88,15 +89,16 @@ export default function cliCommands(): Command {
)
.argParser(parseInt)
.default(10),
).addOption(
program
.createOption(
'--max-concurrent-heroes-per-browser <count>',
'Max number of concurrent Heroes to run per Chrome instance.',
)
.argParser(parseInt)
.default(10),
)
)
.addOption(
program
.createOption(
'--max-concurrent-heroes-per-browser <count>',
'Max number of concurrent Heroes to run per Chrome instance.',
)
.argParser(parseInt)
.default(10),
)
.addOption(
program
.createOption(
Expand Down Expand Up @@ -139,8 +141,77 @@ export default function cliCommands(): Command {
'--datastore-wait-for-completion',
'Wait for all in-process Datastores to complete before shutting down the Cloud node.',
)
.argParser(parseEnvBool)
.default(false),
)
.addOption(
program
.createOption(
'--argon-payment-address <address>',
'The SS58 formatted address to send payments to.',
)
.argParser(x => parseAddress(x, 'Argon Payments Address'))
.env('ARGON_PAYMENT_ADDRESS'),
)
.addOption(
program
.createOption(
'--argon-notary-id <id>',
'The preferred Argon notary to notarize payments with.',
)
.argParser(parseInt)
.env('ARGON_NOTARY_ID'),
)
.addOption(
program
.createOption(
'--argon-localchain-path <path>',
'Activate payment receipt with the given Argon Localchain.',
)
.env('ARGON_LOCALCHAIN_PATH'),
)
.addOption(
program
.createOption(
'--argon-mainchain-url <url>',
'Connect to the given Argon Mainchain rpc url.',
)
.env('ARGON_MAINCHAIN_URL'),
)
.addOption(
program
.createOption(
'--argon-localchain-password <password>',
'Localchain password provided inline (unsafe).',
)
.env('ARGON_LOCALCHAIN_PASSWORD'),
)
.addOption(
program
.createOption(
'--argon-localchain-password-interactive',
'Localchain password prompted on command line.',
)
.argParser(parseEnvBool)
.env('ARGON_LOCALCHAIN_PASSWORD_INTERACTIVE_CLI'),
)
.addOption(
program
.createOption(
'--argon-localchain-password-file <path>',
'Localchain password from a file path.',
)
.env('ARGON_LOCALCHAIN_PASSWORD_FILE'),
)
.addOption(
program
.createOption(
'--argon-block-rewards-address <address>',
'Activate block rewards capture with the given Argon Localchain address.',
)
.argParser(x => parseAddress(x, 'Block Rewards Address'))
.env('ARGON_BLOCK_REWARDS_ADDRESS'),
)
.allowUnknownOption(true)
.action(async opts => {
console.log('Starting Ulixee Cloud with configuration:', opts);
Expand All @@ -152,13 +223,36 @@ export default function cliCommands(): Command {
hostedServicesPort,
hostedServicesHostname,
env,
argonPaymentAddress,
argonNotaryId,
argonLocalchainPath,
argonMainchainUrl,
argonLocalchainPassword,
argonLocalchainPasswordInteractive,
argonLocalchainPasswordFile,
argonBlockRewardsAddress,
} = opts;
if (env) {
applyEnvironmentVariables(Path.resolve(env), process.env);
}
if (disableChromeAlive) CloudNodeEnv.disableChromeAlive = disableChromeAlive;

const { unblockedPlugins, heroDataDir, maxConcurrentHeroes, maxConcurrentHeroesPerBrowser } = opts;
const { unblockedPlugins, heroDataDir, maxConcurrentHeroes, maxConcurrentHeroesPerBrowser } =
opts;
let localchainConfig: ILocalchainConfig;
if (argonLocalchainPath) {
localchainConfig = {
localchainPath: argonLocalchainPath,
mainchainUrl: argonMainchainUrl,
notaryId: argonNotaryId,
keystorePassword: {
password: argonLocalchainPassword ? Buffer.from(argonLocalchainPassword) : undefined,
interactiveCli: argonLocalchainPasswordInteractive,
passwordFile: argonLocalchainPasswordFile,
},
blockRewardsAddress: argonBlockRewardsAddress,
};
}

const cloudNode = new CloudNode(
filterUndefined({
Expand Down Expand Up @@ -186,6 +280,14 @@ export default function cliCommands(): Command {
maxRuntimeMs: opts.maxDatastoreRuntimeMs,
waitForDatastoreCompletionOnShutdown: opts.datastoreWaitForCompletion,
adminIdentities: parseIdentities(opts.adminIdentities, 'Admin Identities'),
paymentInfo:
argonPaymentAddress && argonNotaryId
? {
address: argonPaymentAddress,
notaryId: argonNotaryId,
}
: undefined,
localchainConfig,
}),
}),
);
Expand Down
2 changes: 1 addition & 1 deletion datastore/broker/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function getLocalchainConfig(): ILocalchainConfig | undefined {
return <ILocalchainConfig>{
localchainPath: env.ARGON_LOCALCHAIN_PATH,
mainchainUrl: env.ARGON_MAINCHAIN_URL,
notaryId: parseEnvInt(env.NOTARY_ID),
notaryId: parseEnvInt(env.ARGON_NOTARY_ID),
keystorePassword: {
interactiveCli: parseEnvBool(env.ARGON_LOCALCHAIN_PASSWORD_INTERACTIVE_CLI),
password: keystorePassword,
Expand Down
2 changes: 1 addition & 1 deletion datastore/broker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@ulixee/cloud": "2.0.0-alpha.29",
"@ulixee/commons": "2.0.0-alpha.29",
"@ulixee/datastore": "2.0.0-alpha.29",
"@argonprotocol/localchain": "0.0.6",
"@argonprotocol/localchain": "0.0.8",
"@ulixee/net": "2.0.0-alpha.29",
"@ulixee/platform-specification": "2.0.0-alpha.29",
"@ulixee/platform-utils": "2.0.0-alpha.29",
Expand Down
23 changes: 17 additions & 6 deletions datastore/broker/test/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { toUrl } from '@ulixee/commons/lib/utils';
import { Helpers } from '@ulixee/datastore-testing';
import BrokerChannelHoldSource from '@ulixee/datastore/payments/BrokerChannelHoldSource';
import LocalchainWithSync from '@ulixee/datastore/payments/LocalchainWithSync';
import { ADDRESS_PREFIX } from '@argonprotocol/localchain';
import { ADDRESS_PREFIX, Chain } from '@argonprotocol/localchain';
import { ConnectionToCore, WsTransportToCore } from '@ulixee/net';
import { IDatabrokerAdminApis } from '@ulixee/platform-specification/datastore';
import Identity from '@ulixee/platform-utils/lib/Identity';
Expand Down Expand Up @@ -62,6 +62,11 @@ beforeEach(() => {
afterEach(Helpers.afterEach);
afterAll(Helpers.afterAll);

const mainchainIdentity = {
chain: Chain.Devnet,
genesisHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
};

it('can create channelHolds', async () => {
const broker = new DataBroker({ storageDir });
Helpers.needsClosing.push(broker);
Expand All @@ -85,6 +90,7 @@ it('can create channelHolds', async () => {
recipient: {
address: datastoreKeyPair.address,
notaryId: 1,
...mainchainIdentity,
},
id: 'test',
version: '1.0.0',
Expand All @@ -104,10 +110,12 @@ it('can create channelHolds', async () => {
await broker.onLocalchainSync({
channelHoldNotarizations: [
{
channelHolds: [{
id: channelHold.channelHoldId,
settledAmount: 80n,
}],
channelHolds: [
{
id: channelHold.channelHoldId,
settledAmount: 80n,
},
],
},
],
} as any);
Expand Down Expand Up @@ -137,14 +145,17 @@ test('it rejects invalid signing requests', async () => {
recipient: {
address: datastoreKeyPair.address,
notaryId: 1,
...mainchainIdentity,
},
id: 'test',
version: '1.0.0',
domain: 'test.flights',
};

const client = new BrokerChannelHoldSource(brokerHost.href, await Identity.create());
await expect(client.createChannelHold(paymentInfo, 100n)).rejects.toThrow('Organization not found');
await expect(client.createChannelHold(paymentInfo, 100n)).rejects.toThrow(
'Organization not found',
);

jest
.spyOn(BrokerChannelHoldSource, 'createSignatureMessage')
Expand Down
2 changes: 2 additions & 0 deletions datastore/core/.env.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ULX_ENABLE_GLOBAL_CONFIG=true

## Localchain Configuration

# Alternative configuration to a machine-local localchain
ARGON_PAYMENT_ADDRESS=
# Path to the localchain
ARGON_LOCALCHAIN_PATH=
# Default Argon mainchain host TODO: fill in once mainchain is up#
Expand Down
2 changes: 1 addition & 1 deletion datastore/core/endpoints/ChannelHold.register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default new ValidatingApiHandler('ChannelHold.register', ChannelHoldApisS
request,
context: IDatastoreApiContext,
): Promise<IChannelHoldApiTypes['ChannelHold.register']['result']> {
const manifest = await context.datastoreRegistry.get(request.datastoreId);
const manifest = await context.datastoreRegistry.get(request.datastoreId, null, false);
if (!manifest) throw new Error(`Unknown datastore requested ${request.datastoreId}`);
await context.micropaymentChannelSpendTracker.importChannelHold(request, manifest);
return { accepted: true };
Expand Down
3 changes: 2 additions & 1 deletion datastore/core/endpoints/Datastore.meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export default new DatastoreApiHandler('Datastore.meta', {
async handler(request, context) {
const datastore = await context.datastoreRegistry.get(request.id, request.version);
const stats = await context.statsTracker.getForDatastoreVersion(datastore);
const paymentInfo = await context.paymentInfo;

return translateDatastoreMetadata(datastore, stats, request.includeSchemasAsJson);
return translateDatastoreMetadata(datastore, stats, request.includeSchemasAsJson, paymentInfo);
},
});
3 changes: 3 additions & 0 deletions datastore/core/endpoints/HostedServicesEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ export default class HostedServicesEndpoints {
const manifest = await ctx.datastoreRegistry.get(datastoreId, version);
return await ctx.statsTracker.getForDatastoreVersion(manifest);
},
'MicropaymentChannel.getPaymentInfo': async (_args, ctx) => {
return await ctx.micropaymentChannelSpendTracker.getPaymentInfo();
},
'MicropaymentChannel.importChannelHold': async ({ channelHold, datastoreId }, ctx) => {
const manifest = await ctx.datastoreRegistry.get(datastoreId);
return await ctx.micropaymentChannelSpendTracker.importChannelHold({ channelHold, datastoreId }, manifest);
Expand Down
10 changes: 6 additions & 4 deletions datastore/core/env.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { loadEnv, parseEnvBool, parseEnvInt, parseEnvPath } from '@ulixee/commons/lib/envUtils';
import ILocalchainConfig from '@ulixee/datastore/interfaces/ILocalchainConfig';
import { addressValidation, identityValidation } from '@ulixee/platform-specification/types';
import * as Os from 'os';
import * as Path from 'path';
import ILocalchainConfig from '@ulixee/datastore/interfaces/ILocalchainConfig';

loadEnv(process.cwd());
loadEnv(__dirname);
Expand All @@ -27,6 +27,7 @@ export default {
datastoresMustHaveOwnAdminIdentity: parseEnvBool(env.ULX_DATASTORES_MUST_HAVE_OWN_ADMIN) ?? false,

localchainConfig: getLocalchainConfig(),
argonMainchainUrl: env.ARGON_MAINCHAIN_URL,

enableGlobalConfigs: parseEnvBool(env.ULX_ENABLE_GLOBAL_CONFIG) ?? true,
statsTrackerHost: env.ULX_DATASTORE_STATS_HOST,
Expand All @@ -43,13 +44,14 @@ function getLocalchainConfig(): ILocalchainConfig | undefined {
}
if (env.ARGON_LOCALCHAIN_PASSWORD_FILE)
env.ARGON_LOCALCHAIN_PASSWORD_FILE = parseEnvPath(env.ARGON_LOCALCHAIN_PASSWORD_FILE);
if (env.ARGON_LOCALCHAIN_PATH) env.ARGON_LOCALCHAIN_PATH = parseEnvPath(env.ARGON_LOCALCHAIN_PATH);
if (env.ARGON_LOCALCHAIN_PATH)
env.ARGON_LOCALCHAIN_PATH = parseEnvPath(env.ARGON_LOCALCHAIN_PATH);

return <ILocalchainConfig>{
localchainPath: env.ARGON_LOCALCHAIN_PATH,
mainchainUrl: env.ARGON_MAINCHAIN_URL,
blockRewardsAddress: parseAddress(env.ARGON_BLOCK_REWARDS_ADDRESS, 'Block Rewards Address'),
notaryId: parseEnvInt(env.NOTARY_ID),
notaryId: parseEnvInt(env.ARGON_NOTARY_ID),
keystorePassword: {
interactiveCli: parseEnvBool(env.ARGON_LOCALCHAIN_PASSWORD_INTERACTIVE_CLI),
password: keystorePassword,
Expand All @@ -58,7 +60,7 @@ function getLocalchainConfig(): ILocalchainConfig | undefined {
};
}

function parseAddress(address: string, type: string): string {
export function parseAddress(address: string, type: string): string {
if (!address) return address;
try {
addressValidation.parse(address);
Expand Down
Loading

0 comments on commit b4a9ad5

Please sign in to comment.