Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added ability to load spending plans from environment variable. #3153

Merged
merged 25 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b79887a
feat: Added ability to load spening plans from environment variable.
ebadiere Oct 23, 2024
4415cb3
feat: Now uses one property for either spending plan file or JSON con…
ebadiere Oct 24, 2024
7b806d7
fix: Adding updated package-lock.json
ebadiere Oct 25, 2024
2bcd136
Merge branch 'main' into 3152-spendingplan-as-env-var
ebadiere Oct 25, 2024
f1682cb
fix: Updated global variable reference to the new HBAR_SPENDING_PLANS…
ebadiere Oct 25, 2024
d915ee0
fix: Clean up. Updated logging and appropriate tests.
ebadiere Oct 28, 2024
8c0ad26
Merge branch 'main' into 3152-spendingplan-as-env-var
ebadiere Oct 28, 2024
6beadfd
fix: Replaced the useInMemoryRedisServer with the start and stop redi…
ebadiere Oct 28, 2024
0f0eb73
fix: Test fix. Added the envName back to the loggerService test.
ebadiere Oct 28, 2024
a1570c3
Update docs/configuration.md
ebadiere Oct 29, 2024
07e99d5
fix: Added back file not found tests.
ebadiere Oct 29, 2024
174b5a5
fix: Updated file name in `withOverriddenEnvsInMochaTest` with existi…
ebadiere Oct 29, 2024
eb3f939
fix: Clear the spending plan repository in a test as in CI it seems t…
ebadiere Oct 29, 2024
3f30f72
fix: Added more time for the HBar Rate Limiter to update expenses in …
ebadiere Oct 29, 2024
863f1ab
chore: divided hbar limtier tests into different batches
quiet-node Oct 30, 2024
011aca2
Merge branch '3180-enable-hbar-limiter-acceptance-test-to-run-in-diff…
ebadiere Oct 30, 2024
5aebd00
fix: Removed the clearing of the spending plans.
ebadiere Oct 31, 2024
4b567ca
chore: divided hbar limtier tests into different batches (#3181)
quiet-node Oct 30, 2024
04b193e
Merge branch 'main' into 3152-spendingplan-as-env-var
ebadiere Oct 31, 2024
e8abee6
Update packages/relay/src/lib/config/hbarSpendingPlanConfigService.ts
ebadiere Oct 31, 2024
0c80825
Merge branch '3152-spendingplan-as-env-var' of https://github.com/has…
ebadiere Oct 31, 2024
d1abc7b
fix: Restored class comments and corrected HBAR_SPENDING_PLAN_CONFIG.
ebadiere Oct 31, 2024
4eea649
test: fix hbarSpendingPlanConfigService.spec.ts
victor-yanev Oct 31, 2024
5e1182a
test: remove `.only` from `describe`
victor-yanev Oct 31, 2024
c48d26f
test: disconnect redis client after tests with shared cache
victor-yanev Oct 31, 2024
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
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Unless you need to set a non-default value, it is recommended to only populate o
| `HBAR_RATE_LIMIT_BASIC` | "1120000000" | Individual limit (in tinybars) for spending plans with a BASIC tier. Defaults to 11.2 HBARs. |
| `HBAR_RATE_LIMIT_EXTENDED` | "3200000000" | Individual limit (in tinybars) for spending plans with a EXTENDED tier. Defaults to 32 HBARs. |
| `HBAR_RATE_LIMIT_PRIVILEGED` | "8000000000" | Individual limit (in tinybars) for spending plans with a PRIVILEGED tier. Defaults to 80 HBARs. |
| `HBAR_SPENDING_PLANS_CONFIG_JSON` | "" | Spending plans can be loaded from environment varaibles in JSON format, based on the spendingPlansConfig.example.json file. |
Nana-EC marked this conversation as resolved.
Show resolved Hide resolved
ebadiere marked this conversation as resolved.
Show resolved Hide resolved
| `HBAR_SPENDING_PLANS_CONFIG_FILE` | "spendingPlansConfig.json" | The name of the JSON file containing the pre-configured spending plans for supported projects and partner projects. |
| `HAPI_CLIENT_DURATION_RESET` | "3600000" | Time until client reinitialization. (ms) |
| `HAPI_CLIENT_ERROR_RESET` | [21, 50] | Array of status codes, which when encountered will trigger a reinitialization. Status codes are availble [here](https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto). |
Expand Down
16 changes: 16 additions & 0 deletions packages/relay/src/lib/config/hbarSpendingPlanConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ export class HbarSpendingPlanConfigService {
private readonly SPENDING_PLANS_CONFIG_FILE: string =
ConfigService.get('HBAR_SPENDING_PLANS_CONFIG_FILE') || 'spendingPlansConfig.json';

/**
* The environment variable that contains the spending plans configuration JSON.
*
* @type {string}
* @private
*/
private readonly SPENDING_PLANS_CONFIG_JSON: string | undefined = process.env.HBAR_SPENDING_PLANS_CONFIG_JSON;
ebadiere marked this conversation as resolved.
Show resolved Hide resolved

/**
* Creates an instance of `HbarSpendingPlanConfigService`.
*
Expand Down Expand Up @@ -108,6 +116,14 @@ export class HbarSpendingPlanConfigService {
* @private
*/
private loadSpendingPlansConfig(): SpendingPlanConfig[] {
if (this.SPENDING_PLANS_CONFIG_JSON) {
try {
return JSON.parse(this.SPENDING_PLANS_CONFIG_JSON) as SpendingPlanConfig[];
} catch (error: any) {
throw new Error(`Failed to parse JSON from HBAR_SPENDING_PLANS_CONFIG_JSON: ${error.message}`);
}
}

const configPath = findConfig(this.SPENDING_PLANS_CONFIG_FILE);
if (!configPath || !fs.existsSync(configPath)) {
this.logger.trace(`Configuration file not found at path "${configPath ?? this.SPENDING_PLANS_CONFIG_FILE}"`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ import { Registry } from 'prom-client';

chai.use(chaiAsPromised);

// Dynamically import the service **after** setting the environment variable
async function reloadHBarSPendingPlanConfigService(
hbarSpendingPlanConfigService: HbarSpendingPlanConfigService,
logger,
hbarSpendingPlanRepository: HbarSpendingPlanRepository,
ethAddressHbarSpendingPlanRepository: EthAddressHbarSpendingPlanRepository,
ipAddressHbarSpendingPlanRepository: IPAddressHbarSpendingPlanRepository,
) {
const { HbarSpendingPlanConfigService } = await import('../../../src/lib/config/hbarSpendingPlanConfigService');
hbarSpendingPlanConfigService = new HbarSpendingPlanConfigService(
logger,
hbarSpendingPlanRepository,
ethAddressHbarSpendingPlanRepository,
ipAddressHbarSpendingPlanRepository,
);
return hbarSpendingPlanConfigService;
}

describe('HbarSpendingPlanConfigService', function () {
const logger = pino();
const registry = new Registry();
Expand Down Expand Up @@ -502,6 +520,107 @@ describe('HbarSpendingPlanConfigService', function () {
});
});
});

describe('Environment variable defined spending plans', function () {
const spendingPlansConfigExample = [
ebadiere marked this conversation as resolved.
Show resolved Hide resolved
{
id: 'c758c095-342c-4607-9db5-867d7e90ab9d',
name: 'partner name',
ethAddresses: ['0x123', '0x124'],
ipAddresses: ['127.0.0.1', '128.0.0.1'],
subscriptionTier: 'PRIVILEGED',
},
{
id: 'a68488b0-6f7d-44a0-87c1-774ad64615f2',
name: 'some other partner that has given us only eth addresses',
ethAddresses: ['0x125', '0x126'],
subscriptionTier: 'PRIVILEGED',
},
{
id: 'af13d6ed-d676-4d33-8b9d-cf05d1ad7134',
name: 'supported project name',
ethAddresses: ['0x127', '0x128'],
ipAddresses: ['129.0.0.1', '130.0.0.1'],
subscriptionTier: 'EXTENDED',
},
{
id: '7f665aa3-6b73-41d7-bf9b-92d04cdab96b',
name: 'some other supported project that has given us only ip addresses',
ipAddresses: ['131.0.0.1', '132.0.0.1'],
subscriptionTier: 'EXTENDED',
},
];

describe('when HBAR_SPENDING_PLANS_CONFIG_JSON is not set', function () {
overrideEnvsInMochaDescribe({
HBAR_SPENDING_PLANS_CONFIG_JSON: undefined,
});

it('should not throw an error if the environment variable is not set', async function () {
ebadiere marked this conversation as resolved.
Show resolved Hide resolved
expect(process.env.HBAR_SPENDING_PLANS_CONFIG_JSON).to.be.undefined;
ebadiere marked this conversation as resolved.
Show resolved Hide resolved
await expect(hbarSpendingPlanConfigService.populatePreconfiguredSpendingPlans()).not.to.be.rejected;
});
});

describe('when HBAR_SPENDING_PLANS_CONFIG_JSON is invalid JSON', function () {
before(function () {
delete process.env.HBAR_SPENDING_PLANS_CONFIG_JSON;
process.env.HBAR_SPENDING_PLANS_CONFIG_JSON = 'invalid JSON';
});

after(function () {
delete process.env.HBAR_SPENDING_PLANS_CONFIG_JSON;
});
ebadiere marked this conversation as resolved.
Show resolved Hide resolved

it('should throw an error if environment variable contains invalid JSON', async function () {
hbarSpendingPlanConfigService = await reloadHBarSPendingPlanConfigService(
ebadiere marked this conversation as resolved.
Show resolved Hide resolved
hbarSpendingPlanConfigService,
logger,
hbarSpendingPlanRepository,
ethAddressHbarSpendingPlanRepository,
ipAddressHbarSpendingPlanRepository,
);
await expect(hbarSpendingPlanConfigService.populatePreconfiguredSpendingPlans()).to.be.rejectedWith(
/Failed to parse JSON from HBAR_SPENDING_PLANS_CONFIG_JSON: /,
);
});
});

describe('when HBAR_SPENDING_PLANS_CONFIG_JSON is valid JSON', function () {
before(function () {
process.env.HBAR_SPENDING_PLANS_CONFIG_JSON = JSON.stringify(spendingPlansConfigExample);
});

after(function () {
delete process.env.HBAR_SPENDING_PLANS_CONFIG_JSON;
});
ebadiere marked this conversation as resolved.
Show resolved Hide resolved

it('should populate the database with pre-configured spending plans from the HBAR_SPENDING_PLANS_CONFIG_JSON environment variable', async function () {
hbarSpendingPlanConfigService = await reloadHBarSPendingPlanConfigService(
ebadiere marked this conversation as resolved.
Show resolved Hide resolved
hbarSpendingPlanConfigService,
logger,
hbarSpendingPlanRepository,
ethAddressHbarSpendingPlanRepository,
ipAddressHbarSpendingPlanRepository,
);
await hbarSpendingPlanConfigService.populatePreconfiguredSpendingPlans();

spendingPlansConfigExample.forEach(({ id, name, subscriptionTier }) => {
sinon.assert.calledWith(
hbarSpendingPlanRepositorySpy.create,
subscriptionTier,
emptyRequestDetails,
neverExpireTtl,
id,
);
sinon.assert.calledWith(
loggerSpy.info,
`Created HBAR spending plan "${name}" with ID "${id}" and subscriptionTier "${subscriptionTier}"`,
);
});
});
});
});
};

describe('with shared cache enabled', function () {
Expand Down
Loading