}
+
+
+
+ )
+}
+
+export function SmallGridLink({ link }: { link: GridLink }) {
+ return (
+
+
+
+
+
+
+
+ )
+}
+
const style: Stylesheet = {
container: {
maxWidth: '30em',
@@ -68,4 +95,34 @@ const style: Stylesheet = {
width: '3em',
},
},
+ subText: {
+ fontSize: '0.8em',
+ color: Color.primaryGreen,
+ marginTop: '0.3em',
+ },
+}
+
+const styleSm: Stylesheet = {
+ linkContent: {
+ ...style.linkContent,
+ width: '2.8em',
+ height: '2.8em',
+ margin: '0 0.4em',
+ [mq[480]]: {
+ width: '2.9em',
+ height: '2.9em',
+ margin: '0 0.5em',
+ },
+ [mq[768]]: {
+ width: '3em',
+ height: '3em',
+ margin: '0 0.7em',
+ },
+ },
+ icon: {
+ width: '1.8em',
+ [mq[768]]: {
+ width: '2em',
+ },
+ },
}
diff --git a/src/consts.ts b/src/consts.ts
index d936769c..72bb6713 100644
--- a/src/consts.ts
+++ b/src/consts.ts
@@ -57,3 +57,5 @@ export const DONATION_ADDRESS = '0xE3791A4a231D026c9567BEDbAb977617f2900383' //
export const GOVERNANCE_GITHUB_BASEURL =
'https://api.github.com/repos/celo-org/governance/contents/CGPs/'
+
+export const RAMP_PROJECT_ID = 'jg2gy6y7o35np2w7npw9jnszaz962z3dxhpso4hq'
diff --git a/src/features/governance/fetchDescription.test.ts b/src/features/governance/fetchDescription.test.ts
index 6889b6aa..b87f0855 100644
--- a/src/features/governance/fetchDescription.test.ts
+++ b/src/features/governance/fetchDescription.test.ts
@@ -1,17 +1,45 @@
import { fetchProposalDescription } from 'src/features/governance/fetchDescription'
+import { Proposal, ProposalStage, VoteValue } from 'src/features/governance/types'
// TODO these are causing flaky 403s when running in CI. Skipping for now
xdescribe('fetchProposals', () => {
- it('Fetches and processes as expected', async () => {
- const prop1Desc = await fetchProposalDescription(
- 'https://github.com/celo-org/governance/blob/main/CGPs/cgp-0001.md'
- )
+ const proposal: Proposal = {
+ id: '21',
+ timestamp: 123,
+ description: 'Test prop',
+ url: '',
+ stage: ProposalStage.Referendum,
+ votes: {
+ [VoteValue.Yes]: '1',
+ [VoteValue.No]: '0',
+ [VoteValue.Abstain]: '0',
+ },
+ }
+
+ it('Fetches and processes as expected for old format', async () => {
+ const prop1Desc = await fetchProposalDescription({
+ ...proposal,
+ id: '1',
+ url: 'https://github.com/celo-org/governance/blob/main/CGPs/cgp-0001.md',
+ })
expect(prop1Desc).toBe('Enable validator elections, epoch rewards and carbon offsetting')
- const prop21Desc = await fetchProposalDescription(
- 'https://github.com/celo-org/governance/blob/main/CGPs/cgp-0021.md'
- )
+
+ const prop21Desc = await fetchProposalDescription({
+ ...proposal,
+ id: '21',
+ url: 'https://github.com/celo-org/governance/blob/main/CGPs/cgp-0021.md',
+ })
expect(prop21Desc).toBe(
'Update randomnessBlockRetentionWindow to Extend Attestation Expiration Duration'
)
})
+
+ it('Fetches and processes as expected for new format', async () => {
+ const prop35Desc = await fetchProposalDescription({
+ ...proposal,
+ id: '35',
+ url: 'https://github.com/celo-org/governance/blob/main/CGPs/cgp-0035.md',
+ })
+ expect(prop35Desc).toBe('Reduce the Epoch Rewards Community Fund share from 25% to 5%')
+ })
})
diff --git a/src/features/governance/fetchDescription.ts b/src/features/governance/fetchDescription.ts
index a8ec5f8c..957afc86 100644
--- a/src/features/governance/fetchDescription.ts
+++ b/src/features/governance/fetchDescription.ts
@@ -1,21 +1,24 @@
import { GOVERNANCE_GITHUB_BASEURL } from 'src/consts'
+import { Proposal } from 'src/features/governance/types'
import { logger } from 'src/utils/logger'
// Putting these in a seperate file to faciliate testing for now
-export async function fetchProposalDescription(url: string) {
+export async function fetchProposalDescription(proposal: Proposal) {
try {
- if (!url) throw new Error('No url provided')
- const parsed = new URL(url)
+ if (!proposal || !proposal.url) throw new Error('No url provided')
+ const parsed = new URL(proposal.url)
if (parsed.protocol !== 'https:') throw new Error('Invalid url protocol')
if (parsed.hostname === 'github.com') {
- return fetchProposalDescriptionFromGithub(parsed)
+ const description = await fetchProposalDescriptionFromGithub(parsed)
+ if (!description) throw new Error('No description found')
+ return description
} else {
throw new Error('Only github based urls currently supported')
}
} catch (error) {
logger.error('Failed to retrieve proposal description', error)
- return null
+ return `Proposal #${proposal.id}`
}
}
@@ -38,8 +41,28 @@ async function fetchProposalDescriptionFromGithub(url: URL) {
// TODO find a way to read just the first line if possible, don't actually need the whole file
const text = await response.text()
+ const lines = text.split(/\r?\n/)
+ if (lines[0] === '---') {
+ return parseNewProposalFormat(lines)
+ } else {
+ return parseOldProposalFormat(lines[0])
+ }
+}
+
+function parseOldProposalFormat(line: string) {
const descriptionRegex = /(.*): (.*)/
- const desciptionMatches = text.match(descriptionRegex)
+ const desciptionMatches = line.match(descriptionRegex)
if (desciptionMatches?.length !== 3) throw new Error('Unable to extract proposal description')
return desciptionMatches[2].trim().replace(/(`|#)/gi, '')
}
+
+function parseNewProposalFormat(lines: string[]) {
+ for (let i = 0; i < 15; i++) {
+ const line = lines[i]
+ const descriptionRegex = /title: (.*)/
+ const desciptionMatches = line.match(descriptionRegex)
+ if (desciptionMatches?.length !== 2) continue
+ return desciptionMatches[1].trim().replace(/(`|#)/gi, '')
+ }
+ throw new Error('Unable to extract proposal description')
+}
diff --git a/src/features/governance/fetchProposals.ts b/src/features/governance/fetchProposals.ts
index 7485e97f..77c6e23d 100644
--- a/src/features/governance/fetchProposals.ts
+++ b/src/features/governance/fetchProposals.ts
@@ -95,7 +95,7 @@ export async function fetchCurrentProposals(): Promise {
})
}
- const descriptionsP = proposals.map((p) => fetchProposalDescription(p.url))
+ const descriptionsP = proposals.map((p) => fetchProposalDescription(p))
const descriptions = await Promise.all(descriptionsP)
for (let i = 0; i < numProps; i++) {
proposals[i].description = descriptions[i]
diff --git a/src/features/home/HomeScreenWarnings.tsx b/src/features/home/HomeScreenWarnings.tsx
index db20c559..5fff0ef5 100644
--- a/src/features/home/HomeScreenWarnings.tsx
+++ b/src/features/home/HomeScreenWarnings.tsx
@@ -71,8 +71,9 @@ function AccountKeyReminder() {
const navigate = useNavigate()
return (
- Reminder: Copy your navigate('/wallet')}>Account Key{' '}
- (seed phrase) to a safe place. Your key is the only way to recover your account.
+ Reminder: Copy your{' '}
+ navigate('/wallet')}>Recovery Phrase (seed phrase) to
+ a safe place. Your key is the only way to recover your account.
)
}
diff --git a/src/features/home/Tips.ts b/src/features/home/Tips.ts
index 56aaea31..d953c86f 100644
--- a/src/features/home/Tips.ts
+++ b/src/features/home/Tips.ts
@@ -10,16 +10,16 @@ const Tips = [
'The CELO currency is unstable and limited, like Bitcoin; its value will change over time.',
],
[
- 'To keep your account safe, keep a copy of your Account Key in a private place.',
+ 'To keep your account safe, keep a copy of your recovery (seed) phrase in a private place.',
'For even better security, consider using a Ledger hardware wallet.',
],
[
- "Your Account Address is public; it's like your username on the Celo network. Share it with your friends!",
- 'Your Account Key is a secret; always keep it private.',
+ "Your account address is public; it's like your username on the Celo network. Share it with your friends!",
+ 'Your recovery (seed) phrase is a secret; always keep it private.',
],
[
'Your accounts can be imported in many places at once.',
- 'For example, you can import your Account Key into the Valora mobile app.',
+ 'For example, you can import your recovery (seed) phrase into the Valora mobile app.',
],
[
'You can lock CELO to participate in Celo network elections and governance.',
diff --git a/src/features/onboarding/import/ImportAccountForm.tsx b/src/features/onboarding/import/ImportAccountForm.tsx
index 7ad4b59a..c4b7b2e4 100644
--- a/src/features/onboarding/import/ImportAccountForm.tsx
+++ b/src/features/onboarding/import/ImportAccountForm.tsx
@@ -111,7 +111,7 @@ export function ImportAccountForm(props: Props) {
{!props.hideDescription && (
<>
- Enter your account key (seed phrase).
+ Enter your recovery (seed) phrase.
- To import your account, use your Account Key (seed phrase) or a Ledger hardware wallet.{' '}
+ To import your account, use your recovery (seed) phrase or a Ledger hardware wallet.{' '}
}>
- Use Account Key
+ Use Phrase
}>
Use Ledger
@@ -51,8 +51,8 @@ function HelpModal() {
return (
- If you already have a Celo account, you can use the Account Key to load it here. Account
- Keys are 24 random words (dog chair hello). They are secret so handle them carefully.
+ If you already have a Celo account, you can use the recovery phrase to load it here. Phrases
+ are 12-24 random words (dog chair hello). They are secret so handle them carefully.
If you have a Ledger hardware wallet{' '}
diff --git a/src/features/password/LoginScreen.tsx b/src/features/password/LoginScreen.tsx
index 092638bb..731199d6 100644
--- a/src/features/password/LoginScreen.tsx
+++ b/src/features/password/LoginScreen.tsx
@@ -74,7 +74,7 @@ export function LoginScreen() {
const answer = await showModalAsync({
head: 'Having Trouble Unlocking?',
body: isLocalAcc
- ? "Local accounts can only be unlocked with your password. If you've lost your password, those accounts can unfortunately never be unlocked. But if you have your Account Keys, you can logout to re-import them."
+ ? "Local accounts can only be unlocked with your password. If you've lost your password, those accounts can unfortunately never be unlocked. But if you have your recovery phrase, you can logout to re-import them."
: 'Ledger accounts do not need a password to be unlocked. First open the Celo app on your device, and then click the Unlock button.',
actions: [
{ key: 'back', label: 'Back', color: Color.primaryWhite },
diff --git a/src/features/settings/SettingsScreen.tsx b/src/features/settings/SettingsScreen.tsx
index e820dd3a..61cfb079 100644
--- a/src/features/settings/SettingsScreen.tsx
+++ b/src/features/settings/SettingsScreen.tsx
@@ -61,7 +61,7 @@ export function SettingsScreen() {
-
Account Key
+
Recovery Phrase
Keep this phrase secret and safe.
diff --git a/src/features/wallet/accounts/AddAccountScreen.tsx b/src/features/wallet/accounts/AddAccountScreen.tsx
index 8b0d0220..8516ffbf 100644
--- a/src/features/wallet/accounts/AddAccountScreen.tsx
+++ b/src/features/wallet/accounts/AddAccountScreen.tsx
@@ -60,7 +60,7 @@ export function AddAccountScreen() {
value: NewAccountAction.Create,
label: (
}
/>
@@ -80,7 +80,7 @@ export function AddAccountScreen() {
value: NewAccountAction.Import,
label: (
}
/>
diff --git a/src/features/wallet/accounts/AddDeriveScreen.tsx b/src/features/wallet/accounts/AddDeriveScreen.tsx
index 4646d3fc..a0fe7563 100644
--- a/src/features/wallet/accounts/AddDeriveScreen.tsx
+++ b/src/features/wallet/accounts/AddDeriveScreen.tsx
@@ -91,7 +91,7 @@ export function AddDeriveScreen() {
<>