forked from passportxyz/passport
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app, iam, platforms): adds proof of humanity abstraction (passpo…
…rtxyz#679) Closes passportxyz#630
- Loading branch information
Showing
13 changed files
with
219 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* eslint-disable */ | ||
import { Platform, PlatformOptions } from "../types"; | ||
|
||
export class PohPlatform implements Platform { | ||
getOAuthUrl(state: string): Promise<string> { | ||
throw new Error("Method not implemented."); | ||
} | ||
platformId = "Poh"; | ||
path = "Poh"; | ||
clientId: string = null; | ||
redirectUri: string = null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { PlatformSpec, PlatformGroupSpec } from "../types"; | ||
|
||
export const PohPlatformDetails: PlatformSpec = { | ||
icon: "./assets/pohStampIcon.svg", | ||
platform: "Poh", | ||
name: "Proof of Humanity", | ||
description: "Connect your wallet to start the process of verifying with Proof of Humanity.", | ||
connectMessage: "Connect Account", | ||
isEVM: true, | ||
}; | ||
|
||
export const PohProviderConfig: PlatformGroupSpec[] = [ | ||
{ | ||
platformGroup: "Account Name", | ||
providers: [{ title: "Encrypted", name: "Poh" }], | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// ----- Types | ||
import type { Provider, ProviderOptions } from "../../types"; | ||
import type { RequestPayload, VerifiedPayload } from "@gitcoin/passport-types"; | ||
|
||
// ----- Ethers library | ||
import { Contract } from "ethers"; | ||
import { StaticJsonRpcProvider } from "@ethersproject/providers"; | ||
|
||
// ----- Credential verification | ||
import { getAddress } from "../../utils/signer"; | ||
|
||
// Proof of humanity contract address | ||
const POH_CONTRACT_ADDRESS = "0xC5E9dDebb09Cd64DfaCab4011A0D5cEDaf7c9BDb"; | ||
|
||
// Proof of humanity Contract ABI | ||
const POH_ABI = [ | ||
{ | ||
constant: true, | ||
inputs: [{ internalType: "address", name: "_submissionID", type: "address" }], | ||
name: "isRegistered", | ||
outputs: [{ internalType: "bool", name: "", type: "bool" }], | ||
payable: false, | ||
stateMutability: "view", | ||
type: "function", | ||
}, | ||
]; | ||
|
||
// set the network rpc url based on env | ||
export const RPC_URL = process.env.RPC_URL; | ||
|
||
// Export a Poh Provider to carry out Proof of Humanity account is registered and active check and return a record object | ||
export class PohProvider implements Provider { | ||
// Give the provider a type so that we can select it from a payload | ||
type = "Poh"; | ||
// Options can be set here and/or via the constructor | ||
_options = {}; | ||
|
||
// construct the provider instance with supplied options | ||
constructor(options: ProviderOptions = {}) { | ||
this._options = { ...this._options, ...options }; | ||
} | ||
|
||
// Verify that the address defined in the payload exists in the POH register | ||
async verify(payload: RequestPayload): Promise<VerifiedPayload> { | ||
// if a signer is provider we will use that address to verify against | ||
const address = await getAddress(payload); | ||
|
||
// attempt to verify POH... | ||
try { | ||
// define a provider using the rpc url | ||
const provider: StaticJsonRpcProvider = new StaticJsonRpcProvider(RPC_URL); | ||
|
||
// load Proof of humanity contract | ||
const readContract = new Contract(POH_CONTRACT_ADDRESS, POH_ABI, provider); | ||
|
||
// Checks to see if the address is registered with proof of humanity | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment | ||
const valid: boolean = await readContract.isRegistered(address); | ||
|
||
return { | ||
valid, | ||
record: valid | ||
? { | ||
// store the address into the proof records | ||
address, | ||
} | ||
: undefined, | ||
}; | ||
} catch (e) { | ||
return { | ||
valid: false, | ||
error: [JSON.stringify(e)], | ||
}; | ||
} | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// ---- Test subject | ||
import { RequestPayload } from "@gitcoin/passport-types"; | ||
import { PohProvider } from "../Providers/poh"; | ||
|
||
const mockIsRegistered = jest.fn(); | ||
|
||
jest.mock("ethers", () => { | ||
return { | ||
Contract: jest.fn().mockImplementation(() => { | ||
return { | ||
isRegistered: mockIsRegistered, | ||
}; | ||
}), | ||
}; | ||
}); | ||
|
||
const MOCK_ADDRESS = "0x738488886dd94725864ae38252a90be1ab7609c7"; | ||
|
||
describe("Attempt verification", function () { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it("should return true for an address registered with proof of humanity", async () => { | ||
mockIsRegistered.mockResolvedValueOnce(true); | ||
const poh = new PohProvider(); | ||
const verifiedPayload = await poh.verify({ | ||
address: MOCK_ADDRESS, | ||
} as RequestPayload); | ||
|
||
expect(mockIsRegistered).toBeCalledWith(MOCK_ADDRESS); | ||
expect(verifiedPayload).toEqual({ | ||
valid: true, | ||
record: { | ||
address: MOCK_ADDRESS, | ||
}, | ||
}); | ||
}); | ||
|
||
it("should return false for an address not registered with proof of humanity", async () => { | ||
mockIsRegistered.mockResolvedValueOnce(false); | ||
const UNREGISTERED_ADDRESS = "0xUNREGISTERED"; | ||
|
||
const poh = new PohProvider(); | ||
const verifiedPayload = await poh.verify({ | ||
address: UNREGISTERED_ADDRESS, | ||
} as RequestPayload); | ||
|
||
expect(mockIsRegistered).toBeCalledWith(UNREGISTERED_ADDRESS); | ||
expect(verifiedPayload).toEqual({ | ||
valid: false, | ||
}); | ||
}); | ||
|
||
it("should return error response when isRegistered call errors", async () => { | ||
mockIsRegistered.mockRejectedValueOnce("some error"); | ||
const UNREGISTERED_ADDRESS = "0xUNREGISTERED"; | ||
|
||
const poh = new PohProvider(); | ||
const verifiedPayload = await poh.verify({ | ||
address: UNREGISTERED_ADDRESS, | ||
} as RequestPayload); | ||
|
||
expect(mockIsRegistered).toBeCalledWith(UNREGISTERED_ADDRESS); | ||
expect(verifiedPayload).toEqual({ | ||
valid: false, | ||
error: [JSON.stringify("some error")], | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { PohPlatform } from "./App-Bindings"; | ||
export { PohPlatformDetails, PohProviderConfig } from "./Providers-config"; | ||
export { PohProvider } from "./Providers/poh"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters