Skip to content

Commit

Permalink
Merge pull request #172 from paritytech/yuri/fix-link
Browse files Browse the repository at this point in the history
Fixing tip links
  • Loading branch information
mutantcornholio authored Sep 3, 2024
2 parents a5c0d32 + 242362a commit 7514bcd
Show file tree
Hide file tree
Showing 7 changed files with 379 additions and 147 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ The tests will spin up the local nodes automatically.

To run the tests:

Build the application image:
```bash
yarn build:docker
```

Then run the tests:

```bash
yarn test:integration
```
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"rimraf": "^3.0.2",
"rxjs": "^7.8.1",
"smee-client": "^1.2.2",
"testcontainers": "^10.2.1",
"testcontainers": "^10.13.0",
"ts-jest": "^29.2.4",
"typescript": "^5.4.5"
},
Expand Down
23 changes: 11 additions & 12 deletions src/bot-handle-comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ss58Address } from "@polkadot-labs/hdkd-helpers";
import { updateBalance } from "./balance";
import { matrixNotifyOnFailure, matrixNotifyOnNewTip } from "./matrix";
import { recordTip } from "./metrics";
import { tipUser } from "./tip";
import { tipUser, tipUserLink } from "./tip";
import { updatePolkassemblyPost } from "./tip-opengov";
import { GithubReactionType, State, TipRequest, TipResult } from "./types";
import { formatTipSize, getTipSize, parseContributorAccount } from "./util";
Expand Down Expand Up @@ -167,17 +167,16 @@ export const handleTipRequest = async (
))
) {
let createReferendumLink: string | undefined;
// TODO: Broken after PAPI migration. https://github.com/paritytech/substrate-tip-bot/issues/170
// try {
// const tipLink = await tipUserLink(state, tipRequest);
// if (!tipLink.success) {
// throw new Error(tipLink.errorMessage);
// }
// createReferendumLink = tipLink.extrinsicCreationLink;
// } catch (e) {
// bot.log.error("Failed to encode and create a link to tip referendum creation.");
// bot.log.error(e.message);
// }
try {
const tipLink = await tipUserLink(state, tipRequest);
if (!tipLink.success) {
throw new Error(tipLink.errorMessage);
}
createReferendumLink = tipLink.extrinsicCreationLink;
} catch (e) {
bot.log.error("Failed to encode and create a link to tip referendum creation.");
bot.log.error(e.message);
}

let message =
`Only members of \`${allowedGitHubOrg}/${allowedGitHubTeam}\` ` +
Expand Down
6 changes: 3 additions & 3 deletions src/tip-opengov.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "@polkadot-api/descriptors";
import { ss58Address } from "@polkadot-labs/hdkd-helpers";
import { getDescriptor } from "#src/chain-config";
import { Binary, PolkadotClient, TxPromise } from "polkadot-api";
import { Binary, PolkadotClient, Transaction } from "polkadot-api";
import { Probot } from "probot";

import { Polkassembly } from "./polkassembly/polkassembly";
Expand All @@ -20,7 +20,7 @@ export async function tipOpenGovReferendumExtrinsic(opts: { client: PolkadotClie
| Exclude<TipResult, { success: true }>
| {
success: true;
referendumExtrinsic: { signAndSubmit: TxPromise<"promise"> };
referendumExtrinsic: Transaction<object, "Referenda", "submit", unknown>;
proposalByteSize: number;
encodedProposal: Binary;
track: { track: OpenGovTrack; value: bigint };
Expand All @@ -42,7 +42,7 @@ export async function tipOpenGovReferendumExtrinsic(opts: { client: PolkadotClie

const enactMoment = TraitsScheduleDispatchTime.After(10);

let referendumExtrinsic: { signAndSubmit: TxPromise<"promise"> };
let referendumExtrinsic: Transaction<object, "Referenda", "submit", unknown>;
const network: TipNetwork = tipRequest.contributor.account.network;
if (network === "westend" || network === "localwestend" || network === "rococo" || network === "localrococo") {
const api = client.getTypedApi(getDescriptor(network));
Expand Down
74 changes: 63 additions & 11 deletions src/tip.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,31 @@ describe("tip", () => {
return data.free;
};

const expectTipperMembership = async () => {
await gitHub.forGet("/orgs/tip-bot-org/teams/tip-bot-approvers/memberships/tipper").thenReply(
200,
JSON.stringify(
fixtures.github.getOrgMembershipPayload({
login: "tipper",
org: "tip-bot-approvers",
}),
),
jsonResponseHeaders,
);
};

const expectNoTipperMembership = async () => {
await gitHub.forGet("/orgs/tip-bot-org/teams/tip-bot-approvers/memberships/tipper").thenReply(
404,
JSON.stringify({
message: "Not Found",
documentation_url: "https://docs.github.com/rest/teams/members#get-team-membership-for-a-user",
status: "404",
}),
jsonResponseHeaders,
);
};

beforeAll(async () => {
await fs.mkdir(containterLogsDir, { recursive: true });

Expand All @@ -81,6 +106,7 @@ describe("tip", () => {
.withNetwork(containerNetwork)
.withNetworkAliases("localrococo")
.withExposedPorts(9945)
.withPlatform("linux/amd64")
.start(),
new GenericContainer(`parity/polkadot:${POLKADOT_VERSION}`)
.withWaitStrategy(Wait.forListeningPorts())
Expand All @@ -90,6 +116,7 @@ describe("tip", () => {
.withNetwork(containerNetwork)
.withNetworkAliases("localwestend")
.withExposedPorts(9945)
.withPlatform("linux/amd64")
.start(),
mockServer.startMockServer({ name: "GitHub", port: gitHubPort, testCaCertPath }),
]);
Expand Down Expand Up @@ -199,17 +226,6 @@ describe("tip", () => {
await gitHub
.forPost("/app/installations/155/access_tokens")
.thenReply(200, JSON.stringify(fixtures.github.getAppInstallationTokenPayload()), jsonResponseHeaders);

await gitHub.forGet("/orgs/tip-bot-org/teams/tip-bot-approvers/memberships/tipper").thenReply(
200,
JSON.stringify(
fixtures.github.getOrgMembershipPayload({
login: "tipper",
org: "tip-bot-approvers",
}),
),
jsonResponseHeaders,
);
});

afterAll(async () => {
Expand All @@ -235,6 +251,7 @@ describe("tip", () => {
});

test.each(tipSizes)("tips a user (%s)", async (tipSize) => {
await expectTipperMembership();
const api = network === "localrococo" ? rococoApi : westendApi;
const nextFreeReferendumId = await api.query.Referenda.ReferendumCount.getValue();
await tipUser(appPort, tipSize);
Expand Down Expand Up @@ -272,6 +289,7 @@ describe("tip", () => {
});

test(`huge tip in ${network}`, async () => {
await expectTipperMembership();
const successEndpoint = await gitHub.forPost("/repos/paritytech-stg/testre/issues/4/comments").thenReply(
200,
JSON.stringify(
Expand All @@ -297,6 +315,40 @@ describe("tip", () => {
`The requested tip value of '1000000 ${currency}' exceeds the BigTipper track maximum`,
);
});

test(`tip link in ${network}`, async () => {
await expectNoTipperMembership();
const successEndpoint = await gitHub.forPost("/repos/paritytech-stg/testre/issues/4/comments").thenReply(
200,
JSON.stringify(
fixtures.github.getIssueCommentPayload({
org: "paritytech-stg",
repo: "testre",
comment: {
author: "substrate-tip-bot",
body: "",
id: 4,
},
}),
),
);

await tipUser(appPort, "small");

await until(async () => !(await successEndpoint.isPending()), 500, 50);

const [request] = await successEndpoint.getSeenRequests();
const body = (await request.body.getJson()) as { body: string };
expect(body.body).toContain(
"Only members of `tip-bot-org/tip-bot-approvers` have permission to request the creation of the tip referendum from the bot.",
);
expect(body.body).toContain(`https://polkadot.js.org/apps/?rpc=ws://localrococo:9945#/`);

const extrinsicHex = body.body.match(/decode\/(\w+)/)?.[1];
expect(extrinsicHex).toBeDefined();

// TODO: validate the contents of the extrinsic, when such functionality will be available in PAPI
});
});
});

Expand Down
7 changes: 4 additions & 3 deletions src/tip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ export async function tipUserLink(
return preparedExtrinsic;
}

const { botTipAccount } = state;
const transactionHex = (await preparedExtrinsic.referendumExtrinsic.getEncodedData()).asHex();

const { txHash } = await preparedExtrinsic.referendumExtrinsic.signAndSubmit(botTipAccount);
const polkadotAppsUrl = `https://polkadot.js.org/apps/?rpc=${papiConfig.entries[network].wsUrl}#/`;
const extrinsicCreationLink = `${polkadotAppsUrl}extrinsics/decode/${txHash}`;
const extrinsicCreationLink = `${polkadotAppsUrl}extrinsics/decode/${transactionHex}`;
return { success: true, extrinsicCreationLink };
} catch (e) {
return { success: false, errorMessage: e instanceof Error ? e.stack ?? e.message : String(e) };
} finally {
client.destroy();
}
Expand Down
Loading

0 comments on commit 7514bcd

Please sign in to comment.