Skip to content

Commit

Permalink
Add phone number sybil resistance endpoint for snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
calebtuttle committed Mar 21, 2023
1 parent 1c9fc0b commit 978d806
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 11 deletions.
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ We plan to support more chains in the future. If you would like to use Holonym o
- **GET** `/sybil-resistance/phone/<network>`
- **GET** `/snapshot-strategies/residence/country/us`
- **GET** `/snapshot-strategies/sybil-resistance/gov-id`
- **GET** `/snapshot-strategies/sybil-resistance/phone`

### **GET** `/residence/country/us/<network>?user=<user-address>`

Expand Down Expand Up @@ -167,7 +168,7 @@ To use with the ["api"](https://github.com/snapshot-labs/snapshot-strategies/tre

### **GET** `/snapshot-strategies/sybil-resistance/gov-id?network=<network>&snapshot=<snapshot>&addresses=<addresses>&action-id=<action-id>`

Returns a list of scores indicating, for each address, whether the address has submitted a valid proof of uniqueness for the given action-id.
Returns a list of scores indicating, for each address, whether the address has submitted a valid proof of uniqueness (using government ID) for the given action-id.

Every score is either 1 or 0.

Expand Down Expand Up @@ -224,6 +225,65 @@ To use with the ["api"](https://github.com/snapshot-labs/snapshot-strategies/tre
}
```

### **GET** `/snapshot-strategies/sybil-resistance/phone?network=<network>&snapshot=<snapshot>&addresses=<addresses>&action-id=<action-id>`

Returns a list of scores indicating, for each address, whether the address has submitted a valid proof of uniqueness (using phone number) for the given action-id.

Every score is either 1 or 0.

| score | description |
| ----- | ------------------------------------------------- |
| 1 | Address has proven uniqueness for action-id |
| 0 | Address has _not_ proven uniqueness for action-id |

#### Use with Snapshot

To use with the ["api"](https://github.com/snapshot-labs/snapshot-strategies/tree/master/src/strategies/api) Snapshot strategy, specify the strategy parameters using the following format. We suggest that you use the default action-id `123456789`. If you are using a different action-id, replace `123456789` with your action-id.

{
"api": "https://api.holonym.io",
"symbol": "",
"decimals": 0,
"strategy": "snapshot-strategies/sybil-resistance/phone",
"additionalParameters": "action-id=123456789"
}

#### Use without Snapshot

- Parameters

| name | description | type | in | required |
| ----------- | ---------------------------------------------- | ------ | ----- | -------- |
| `network` | Chain ID | string | query | true |
| `snapshot` | Block height | string | query | true |
| `addresses` | List of blockchain address separated by commas | string | query | true |

- Example

```JavaScript
const resp = await fetch('https://api.holonym.io/snapshot-strategies/sybil-resistance/phone?network=420&snapshot=9001&addresses=0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000001&action-id=123');
const data = await resp.json();
```

- Responses

- 200

```JSON
{
"score" : [
{
"address" : "0x0000000000000000000000000000000000000000",
"score" : 0
},
{
"address" : "0x0000000000000000000000000000000000000001",
"score" : 1
}
]
}
```

## Sybil resistance

The `sybil-resistance` endpoint uses blockchain-address + action-id pairings to establish uniqueness.
Expand Down
9 changes: 7 additions & 2 deletions src/routes/snapshot-strategies.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import express from "express";
import { residesInUS, sybilResistance } from "../services/snapshot-strategies.js";
import {
residesInUS,
sybilResistanceGovId,
sybilResistancePhone,
} from "../services/snapshot-strategies.js";

const router = express.Router();

router.get("/residence/country/us", residesInUS);
router.get("/sybil-resistance/gov-id", sybilResistance);
router.get("/sybil-resistance/gov-id", sybilResistanceGovId);
router.get("/sybil-resistance/phone", sybilResistancePhone);

export default router;
75 changes: 67 additions & 8 deletions src/services/snapshot-strategies.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { defaultActionId } from "../constants/misc.js";
import {
resStoreAddrsByNetwork,
sybilResistanceAddrsByNetwork,
sybilResistancePhoneAddrsByNetwork,
} from "../constants/contractAddresses.js";
import ResidencyStoreABI from "../constants/ResidencyStoreABI.js";
import AntiSybilStoreABI from "../constants/AntiSybilStoreABI.js";
Expand Down Expand Up @@ -78,12 +79,12 @@ async function residesInUS(req, res) {
* action-id param must be passed as to options.additionalParameters in strategy.
* For example, "action-id=123"
*/
async function sybilResistance(req, res) {
async function sybilResistanceGovId(req, res) {
// TODO: Add support for `network` param
logWithTimestamp("strategies/sybilResistance: Entered");
logWithTimestamp("strategies/sybilResistanceGovId: Entered");
if (!req.query.addresses) {
logWithTimestamp(
"strategies/sybilResistance: No addresses in query params. Exiting"
"strategies/sybilResistanceGovId: No addresses in query params. Exiting"
);
return res
.status(400)
Expand All @@ -96,20 +97,78 @@ async function sybilResistance(req, res) {
.json({ error: "Request query params do not include snapshot" });
}

const network = req.query.network == "420" ? "optimism-goerli" : "optimism";
const network = req.query.network === "420" ? "optimism-goerli" : "optimism";
const contractAddr = sybilResistanceAddrsByNetwork[network];
const provider = providers[network];
const contract = new ethers.Contract(contractAddr, AntiSybilStoreABI, provider);

const snapshot = parseInt(req.query.snapshot);
const currentBlockNumber = await provider.getBlockNumber();
if (snapshot < 0 || snapshot > currentBlockNumber) {
logWithTimestamp("strategies/residesInUS: Snapshot is invalid. Exiting");
logWithTimestamp("strategies/sybilResistanceGovId: Snapshot is invalid. Exiting");
return res.status(400).json({ error: "Snapshot is invalid" });
}

const actionId =
typeof req.query?.["action-id"] === "number"
? parseInt(req.query?.["action-id"])
: defaultActionId;

const overrides = {
blockTag: parseInt(req.query.snapshot),
};

let scores = [];
const addresses = req.query.addresses.split(",");
for (const address of addresses) {
try {
const isUnique = await contract.isUniqueForAction(address, actionId); //, overrides);
scores.push({ address: address, score: isUnique ? 1 : 0 });
} catch (err) {
console.log(err);
logWithTimestamp(
`strategies/sybilResistanceGovId: Encountered error while calling smart contract for address ${address}. Exiting`
);
return res.status(500).json({ error: "An unexpected error occured" });
}
}
return res.status(200).json({ score: scores });
}

// TODO: sybilResistancePhone is the same as sybilResistancePhone, except for contract address.
// Rewrite to remove code duplication.
async function sybilResistancePhone(req, res) {
// TODO: Add support for `network` param
logWithTimestamp("strategies/sybilResistancePhone: Entered");
if (!req.query.addresses) {
logWithTimestamp(
"strategies/sybilResistancePhone: No addresses in query params. Exiting"
);
return res
.status(400)
.json({ error: "Request query params do not include addresses" });
}
if (!req.query.snapshot) {
logWithTimestamp("strategies/residesInUS: No snapshot in query params. Exiting");
return res
.status(400)
.json({ error: "Request query params do not include snapshot" });
}

const network = req.query.network === "420" ? "optimism-goerli" : "optimism";
const contractAddr = sybilResistancePhoneAddrsByNetwork[network];
const provider = providers[network];
const contract = new ethers.Contract(contractAddr, AntiSybilStoreABI, provider);

const snapshot = parseInt(req.query.snapshot);
const currentBlockNumber = await provider.getBlockNumber();
if (snapshot < 0 || snapshot > currentBlockNumber) {
logWithTimestamp("strategies/sybilResistancePhone: Snapshot is invalid. Exiting");
return res.status(400).json({ error: "Snapshot is invalid" });
}

const actionId =
typeof req.query?.["action-id"] == "number"
typeof req.query?.["action-id"] === "number"
? parseInt(req.query?.["action-id"])
: defaultActionId;

Expand All @@ -126,12 +185,12 @@ async function sybilResistance(req, res) {
} catch (err) {
console.log(err);
logWithTimestamp(
`strategies/sybilResistance: Encountered error while calling smart contract for address ${address}. Exiting`
`strategies/sybilResistancePhone: Encountered error while calling smart contract for address ${address}. Exiting`
);
return res.status(500).json({ error: "An unexpected error occured" });
}
}
return res.status(200).json({ score: scores });
}

export { residesInUS, sybilResistance };
export { residesInUS, sybilResistanceGovId, sybilResistancePhone };

0 comments on commit 978d806

Please sign in to comment.